diff --git a/.lock b/.lock new file mode 100644 index 0000000..e69de29 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/crates.js b/crates.js new file mode 100644 index 0000000..346a404 --- /dev/null +++ b/crates.js @@ -0,0 +1 @@ +window.ALL_CRATES = ["magic_regexp"]; \ No newline at end of file diff --git a/help.html b/help.html new file mode 100644 index 0000000..319f51f --- /dev/null +++ b/help.html @@ -0,0 +1,2 @@ +
Redirecting to ../../../magic_regexp/enum.Error.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/core/traits/trait.AsRegex.html b/magic_regexp/core/traits/trait.AsRegex.html new file mode 100644 index 0000000..c234848 --- /dev/null +++ b/magic_regexp/core/traits/trait.AsRegex.html @@ -0,0 +1,11 @@ + + + + +Redirecting to ../../../magic_regexp/trait.AsRegex.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/core/traits/trait.Condition.html b/magic_regexp/core/traits/trait.Condition.html new file mode 100644 index 0000000..5df0422 --- /dev/null +++ b/magic_regexp/core/traits/trait.Condition.html @@ -0,0 +1,11 @@ + + + + +Redirecting to ../../../magic_regexp/trait.Condition.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/core/traits/type.Result.html b/magic_regexp/core/traits/type.Result.html new file mode 100644 index 0000000..1c78cd8 --- /dev/null +++ b/magic_regexp/core/traits/type.Result.html @@ -0,0 +1,11 @@ + + + + +Redirecting to ../../../magic_regexp/type.Result.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/core/type/enum.Input.html b/magic_regexp/core/type/enum.Input.html new file mode 100644 index 0000000..100fb3a --- /dev/null +++ b/magic_regexp/core/type/enum.Input.html @@ -0,0 +1,11 @@ + + + + +Redirecting to ../../../magic_regexp/enum.Input.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/core/type/enum.Type.html b/magic_regexp/core/type/enum.Type.html new file mode 100644 index 0000000..54e3f32 --- /dev/null +++ b/magic_regexp/core/type/enum.Type.html @@ -0,0 +1,11 @@ + + + + +Redirecting to ../../../magic_regexp/enum.Type.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/core/type/fn.not.html b/magic_regexp/core/type/fn.not.html new file mode 100644 index 0000000..4f467d5 --- /dev/null +++ b/magic_regexp/core/type/fn.not.html @@ -0,0 +1,11 @@ + + + + +Redirecting to ../../../magic_regexp/fn.not.html...
+ + + \ No newline at end of file diff --git a/magic_regexp/enum.Error.html b/magic_regexp/enum.Error.html new file mode 100644 index 0000000..73295f5 --- /dev/null +++ b/magic_regexp/enum.Error.html @@ -0,0 +1,17 @@ +pub enum Error {
+ RegexError(Error),
+}
An error, which can occur while using this crate. +Mostly used to wrap errors from the Regex crate.
+pub enum Input<'a> {
+ OneOrMore(Type<'a>),
+ Exactly(Type<'a>),
+ Maybe(Type<'a>),
+ Times(Type<'a>, usize),
+}
This is a regex input that can be used to match a single character or a group of characters.
+Can be used to create a regex that matches a single character or a group of characters.
+For example, Input::Exactly(Type::Digit)
will match a single digit.
use magic_regexp::{create_reg_exp, Input, Type};
+
+let regex = create_reg_exp(Input::Exactly(Type::Digit)).unwrap();
+assert!(regex.is_match("1"));
+assert!(!regex.is_match("12"));
+assert!(regex.is_match("1 2"));
use magic_regexp::{create_reg_exp, Input, Type};
+
+let regex = create_reg_exp(Input::OneOrMore(Type::Digit)).unwrap();
+assert!(regex.is_match("1"));
+assert!(regex.is_match("12"));
+assert!(regex.is_match("1 2"));
use magic_regexp::{create_reg_exp, Input, Type};
+
+let regex = create_reg_exp(Input::Maybe(Type::Digit)).unwrap();
+assert!(regex.is_match("1"));
+assert!(regex.is_match(""));
+assert!(regex.is_match("12"));
+assert!(regex.is_match("a"));
+assert!(regex.is_match("1 2"));
This defines the entire input so far as a named capture group.
+use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase, OneOrMore};
+
+let regex = create_reg_exp(OneOrMore(Digit).grouped_as("digits")).unwrap();
+assert_eq!(®ex.captures("1").unwrap()["digits"], "1");
This defines the entire input so far as a named capture group.
+This is an alias for grouped_as
.
This defines the entire input so far as an anonymous group.
+use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase, OneOrMore, Type, Char, Whitespace, Maybe, Options};
+use regex::Regex;
+
+let regex = create_reg_exp(OneOrMore(Digit).grouped()
+ .and(Exactly(Whitespace))
+ .and(OneOrMore(Char).or(Exactly(Whitespace)).optionally())
+ .and(OneOrMore(Digit).grouped())
+).unwrap();
+assert_eq!(®ex.captures("1 5").unwrap()[1], "1");
+assert_eq!(®ex.captures("134 23").unwrap()[1], "134");
+// The folloing example is not really useful, because it shows only the first match.
+// The second match is not captured. See the next example for a more useful example.
+assert_eq!(®ex.captures("this is the 134 test 213").unwrap()[1], "134");
+// This is a bit more complex, because we are using anonymous groups in regex.
+let cap = ®ex
+ .find_iter("multiple numbers 134 2123")
+ .filter_map(|digits| digits.as_str().parse().ok())
+ .collect::<Vec<String>>()
+ .join(" ");
+let expected = ["134", "2123"].join(" ");
+assert_eq!(cap, &expected);
Returns a Regex, which chains the 2 given regexes with an and
operator.
use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase};
+
+let regex = create_reg_exp(Exactly(Digit).or(Exactly(LetterLowercase))).unwrap();
+assert!(regex.is_match("1"));
+assert!(regex.is_match("a"));
+assert!(!regex.is_match("A"));
+assert!(!regex.is_match("12"));
+assert!(!regex.is_match("1a"));
+assert!(regex.is_match("1 a"));
and
condition.or
condition.pub enum Type<'a> {
+Show 24 variants
Digit,
+ NotDigit,
+ WordBoundary,
+ NotWordBoundary,
+ Word,
+ WordChar,
+ NotWordChar,
+ Text(&'a str),
+ Options(&'a str),
+ Char,
+ Whitespace,
+ NotWhitespace,
+ Letter,
+ NotLetter,
+ LetterLowercase,
+ NotLetterLowercase,
+ LetterUppercase,
+ NotLetterUppercase,
+ Tab,
+ NotTab,
+ Linefeed,
+ NotLinefeed,
+ CarriageReturn,
+ NotCarriageReturn,
+}
Represents a regex type. This enum is used to create the smallest regex statement.
+For example, Type::Digit
will create the regex \d
.
use magic_regexp::{OneOrMore, Type::Digit};
+
+let input = OneOrMore(Digit);
+assert_eq!(input.to_string(), r"(\d+)"); // Note that the regex is wrapped in parentheses.
pub fn create_reg_exp(input: impl AsRegex) -> Result<Regex>
Returns the regex, which represents the given statement. +This is only for convenience and compatibility with magic-regex from npm.
+use magic_regexp::{Digit, Times, create_reg_exp, Exactly, Condition, Text};
+use regex::Regex;
+
+const TO_SEARCH: &'static str = "On 2010-03-14, foo happened. On 2014-10-14, bar happened.";
+let input = Times(Digit, 4).and(Exactly(Text("-"))).and(Times(Digit, 2)).and(Exactly(Text(("-")))).and(Times(Digit, 2));
+assert_eq!(input.to_string(), r"\d{4}-\d{2}-\d{2}");
+let input = Times(Digit, 4).grouped_as("year").and(Exactly(Text("-"))).and(Times(Digit, 2).grouped_as("month")).and(Exactly(Text(("-")))).and(Times(Digit, 2).grouped_as("day"));
+let re = create_reg_exp(input).unwrap();
+assert!(re.is_match("2014-01-01"));
+assert_eq!(re.find_iter(TO_SEARCH).count(), 2);
+for caps in re.captures_iter(TO_SEARCH) {
+ // Note that all of the unwraps are actually OK for this regex
+ // because the only way for the regex to match is if all of the
+ // capture groups match. This is not true in general though!
+println!("year: {}, month: {}, day: {}",
+ caps.get(1).unwrap().as_str(),
+ caps.get(2).unwrap().as_str(),
+ caps.get(3).unwrap().as_str());
+}
pub fn not(t: Type<'_>) -> Type<'_>
Returns the opposite of the given type.
+For example, Type::Digit
will return Type::NotDigit
.
+Returns the same type if it is not a type that can be negated.
Panics, if the given type is Type::Options
and the given string is empty.
use magic_regexp::{OneOrMore, not, Options};
+
+let input = OneOrMore(not(not(Options("01"))));
+assert_eq!(input.to_string(), r"([01]+)");
This crate provides a library for creating regular expressions in a more readable way. +It stands on the shoulders of the regex crate.
+For more specific details on the API for regular expressions, please see around the enums in the left sidebar.
+use magic_regexp::{Digit, Times, create_reg_exp, Exactly, Condition, Text};
+use regex::Regex;
+
+const TO_SEARCH: &'static str = "On 2010-03-14, foo happened. On 2014-10-14, bar happened.";
+let input = Times(Digit, 4).and(Exactly(Text("-"))).and(Times(Digit, 2)).and(Exactly(Text(("-")))).and(Times(Digit, 2));
+assert_eq!(input.to_string(), r"\d{4}-\d{2}-\d{2}");
+
+let input = Times(Digit, 4).grouped_as("year").and(Exactly(Text("-"))).and(Times(Digit, 2).grouped_as("month")).and(Exactly(Text(("-")))).and(Times(Digit, 2).grouped_as("day"));
+let re = create_reg_exp(input).unwrap();
+assert!(re.is_match("2014-01-01"));
+assert_eq!(re.find_iter(TO_SEARCH).count(), 2);
+
+for caps in re.captures_iter(TO_SEARCH) {
+ // Note that all of the unwraps are actually OK for this regex
+ // because the only way for the regex to match is if all of the
+ // capture groups match. This is not true in general though!
+ println!("year: {}, month: {}, day: {}",
+ caps.get(1).unwrap().as_str(),
+ caps.get(2).unwrap().as_str(),
+ caps.get(3).unwrap().as_str());
+}
Input::Exactly(Type::Digit)
will match a single digit.Type::Digit
will create the regex \d
.and
, or
and optionally
methods and chain statements.Type::Digit
will return Type::NotDigit
.
+Returns the same type if it is not a type that can be negated.pub trait AsRegex: ToString {
+ // Provided method
+ fn as_regex(&self) -> Result<Regex> { ... }
+}
A trait, which allows to convert something to a regex. +Mostly needed to work with this lib and Regex crate.
+pub trait Condition: AsRegex + Sized {
+ // Provided methods
+ fn and(self, other: impl AsRegex) -> Regex { ... }
+ fn or(self, other: impl AsRegex) -> Regex { ... }
+ fn optionally(self) -> Regex { ... }
+}
A trait, which allows to chain regex statements with conditions.
+Import this, if you want to use the and
, or
and optionally
methods and chain statements.
Returns the regex, which chains the two given statements with an and
condition.
Returns the regex, which chains the two given statements with an or
condition.
Returns the regex, which sets the given statement to optional.
+Returns a Regex, which chains the 2 given regexes with an and
operator.
use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase};
+
+let regex = create_reg_exp(Exactly(Digit).or(Exactly(LetterLowercase))).unwrap();
+assert!(regex.is_match("1"));
+assert!(regex.is_match("a"));
+assert!(!regex.is_match("A"));
+assert!(!regex.is_match("12"));
+assert!(!regex.is_match("1a"));
+assert!(regex.is_match("1 a"));
U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Returns the opposite of the given type. For example, …","Returns the regex, which sets the given statement to …","Returns the regex, which sets the given statement to …","Returns the regex, which chains the two given statements …","Returns the regex, which chains the two given statements …","","","","","","","","","","","","",""],"i":[0,7,7,0,7,6,0,4,0,7,7,7,7,4,7,7,7,7,7,7,7,7,7,7,6,4,7,10,0,7,7,4,0,7,7,7,7,1,1,4,3,3,4,7,4,10,7,4,10,0,7,4,10,10,7,4,10,10,4,4,7,4,10,0,1,1,1,1,10,7,4,10,7,4,10,7,4,10,7,4,10],"f":"`````````````````````````````````````{{bc}df}0{{hj}d}{f{{l{d}}}}0{h{{l{d}}}}{ce{}{}}00000{c{{l{d}}}f}{{nA`}Ab}{{hA`}Ab}{{AdA`}Ab}0{cc{}}00{AfAd}{hd}:777{nn}{bd}0=={Ad{{Aj{Ah}}}}{cAl{}}00{c{{An{e}}}{}{}}00000{cB`{}}00","c":[],"p":[[10,"Condition",0],[5,"Regex",81],[10,"AsRegex",0],[6,"Input",0],[1,"str"],[8,"Result",0],[6,"Type",0],[5,"Formatter",82],[8,"Result",82],[6,"Error",0],[6,"Error",83],[10,"Error",84],[6,"Option",85],[5,"String",86],[6,"Result",87],[5,"TypeId",88]],"b":[[52,"impl-Debug-for-Error"],[53,"impl-Display-for-Error"]]}]\
+]'));
+if (typeof exports !== 'undefined') exports.searchIndex = searchIndex;
+else if (window.initSearch) window.initSearch(searchIndex);
diff --git a/settings.html b/settings.html
new file mode 100644
index 0000000..c337932
--- /dev/null
+++ b/settings.html
@@ -0,0 +1,2 @@
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +
use regex::Regex;
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+/// An error, which can occur while using this crate.
+/// Mostly used to wrap errors from the Regex crate.
+pub enum Error {
+ #[error("An regex error occurred")]
+ RegexError(#[from] regex::Error),
+}
+
+/// A type, which is used to return results from this crate.
+/// Mostly used to wrap results from the Regex crate.
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// A trait, which allows to convert something to a regex.
+/// Mostly needed to work with this lib and Regex crate.
+pub trait AsRegex: ToString {
+ /// Returns the regex, which represents the wanted statement.
+ fn as_regex(&self) -> Result<Regex> {
+ let regex = Regex::new(&self.to_string())?;
+ Ok(regex)
+ }
+}
+
+/// A trait, which allows to chain regex statements with conditions.
+/// Import this, if you want to use the `and`, `or` and `optionally` methods and chain statements.
+pub trait Condition: AsRegex + Sized {
+ /// Returns the regex, which chains the two given statements with an `and` condition.
+ fn and(self, other: impl AsRegex) -> Regex {
+ Regex::new(&format!("{}{}", self.to_string(), other.to_string()))
+ .expect("Invalid regex (and)")
+ }
+ /// Returns the regex, which chains the two given statements with an `or` condition.
+ fn or(self, other: impl AsRegex) -> Regex {
+ Regex::new(&format!("{}|{}", self.to_string(), other.to_string()))
+ .expect("Invalid regex (or)")
+ }
+ /// Returns the regex, which sets the given statement to optional.
+ fn optionally(self) -> Regex {
+ Regex::new(&format!("(?:{})?", self.to_string())).expect("Invalid regex (optionally)")
+ }
+}
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +
use std::fmt::{Display};
+use crate::{AsRegex, Condition, Result};
+use regex::Regex;
+
+/// Represents a regex type. This enum is used to create the smallest regex statement.
+/// For example, `Type::Digit` will create the regex `\d`.
+///
+/// # Examples
+/// ```
+/// use magic_regexp::{OneOrMore, Type::Digit};
+///
+/// let input = OneOrMore(Digit);
+/// assert_eq!(input.to_string(), r"(\d+)"); // Note that the regex is wrapped in parentheses.
+/// ```
+pub enum Type<'a> {
+ Digit,
+ NotDigit,
+ WordBoundary,
+ NotWordBoundary,
+ Word,
+ WordChar,
+ NotWordChar,
+ Text(&'a str),
+ Options(&'a str),
+ Char,
+ Whitespace,
+ NotWhitespace,
+ Letter,
+ NotLetter,
+ LetterLowercase,
+ NotLetterLowercase,
+ LetterUppercase,
+ NotLetterUppercase,
+ Tab,
+ NotTab,
+ Linefeed,
+ NotLinefeed,
+ CarriageReturn,
+ NotCarriageReturn,
+}
+
+impl<'a> AsRegex for Type<'a> {}
+
+impl<'a> Display for Type<'a> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let txt;
+ let str = match self {
+ Type::Digit => r"\d",
+ Type::NotDigit => r"\D",
+ Type::WordBoundary => r"\b",
+ Type::NotWordBoundary => r"\B",
+ Type::Word => r"\b\w+\b",
+ Type::WordChar => r"\w",
+ Type::NotWordChar => r"\W",
+ Type::Char => r".",
+ Type::Text(text) => text,
+ Type::Whitespace => r"\s",
+ Type::NotWhitespace => r"\S",
+ Type::Letter => r"[a-zA-Z]",
+ Type::NotLetter => r"[^a-zA-Z]",
+ Type::LetterLowercase => r"[a-z]",
+ Type::NotLetterLowercase => r"[^a-z]",
+ Type::LetterUppercase => r"[A-Z]",
+ Type::NotLetterUppercase => r"[^A-Z]",
+ Type::Tab => r"\t",
+ Type::NotTab => r"^\t",
+ Type::Linefeed => r"\n",
+ Type::NotLinefeed => r"^\n",
+ Type::CarriageReturn => r"\r",
+ Type::NotCarriageReturn => r"^\r",
+ Type::Options(options) => {
+ txt = format!("[{}]", options);
+ txt.as_str()
+ }
+ }
+ .to_string();
+ write!(f, "{}", str)
+ }
+}
+
+/// Returns the opposite of the given type.
+/// For example, `Type::Digit` will return `Type::NotDigit`.
+/// Returns the same type if it is not a type that can be negated.
+///
+/// Panics, if the given type is `Type::Options` and the given string is empty.
+///
+/// # Examples
+/// ```
+/// use magic_regexp::{OneOrMore, not, Options};
+///
+/// let input = OneOrMore(not(not(Options("01"))));
+/// assert_eq!(input.to_string(), r"([01]+)");
+/// ```
+pub fn not(t: Type) -> Type {
+ match t {
+ Type::Digit => Type::NotDigit,
+ Type::NotDigit => Type::Digit,
+ Type::WordBoundary => Type::NotWordBoundary,
+ Type::NotWordBoundary => Type::WordBoundary,
+ Type::WordChar => Type::NotWordChar,
+ Type::NotWordChar => Type::WordChar,
+ Type::Whitespace => Type::NotWhitespace,
+ Type::NotWhitespace => Type::Whitespace,
+ Type::Letter => Type::NotLetter,
+ Type::NotLetter => Type::Letter,
+ Type::LetterLowercase => Type::NotLetterLowercase,
+ Type::NotLetterLowercase => Type::LetterLowercase,
+ Type::LetterUppercase => Type::NotLetterUppercase,
+ Type::NotLetterUppercase => Type::LetterUppercase,
+ Type::Tab => Type::NotTab,
+ Type::NotTab => Type::Tab,
+ Type::Linefeed => Type::NotLinefeed,
+ Type::NotLinefeed => Type::Linefeed,
+ Type::CarriageReturn => Type::NotCarriageReturn,
+ Type::NotCarriageReturn => Type::CarriageReturn,
+ Type::Text(t) => Type::Text(Box::leak(format!("^{}", t).into_boxed_str())),
+ Type::Options(t) => {
+ if let Some(first) = t.chars().next() {
+ let opt: String = if first == '^' {
+ t[1..].to_string()
+ } else {
+ format!("^{}", t)
+ };
+ Type::Options(Box::leak(opt.into_boxed_str()))
+ } else {
+ panic!("Invalid options: {}", t);
+ }
+ }
+ _ => t,
+ }
+}
+
+/// This is a regex input that can be used to match a single character or a group of characters.
+/// Can be used to create a regex that matches a single character or a group of characters.
+/// For example, `Input::Exactly(Type::Digit)` will match a single digit.
+///
+/// # Example
+/// ```
+/// use magic_regexp::{create_reg_exp, Input, Type};
+///
+/// let regex = create_reg_exp(Input::Exactly(Type::Digit)).unwrap();
+/// assert!(regex.is_match("1"));
+/// assert!(!regex.is_match("12"));
+/// assert!(regex.is_match("1 2"));
+/// ```
+///
+/// # Example
+/// ```
+/// use magic_regexp::{create_reg_exp, Input, Type};
+///
+/// let regex = create_reg_exp(Input::OneOrMore(Type::Digit)).unwrap();
+/// assert!(regex.is_match("1"));
+/// assert!(regex.is_match("12"));
+/// assert!(regex.is_match("1 2"));
+/// ```
+///
+/// # Example
+/// ```
+/// use magic_regexp::{create_reg_exp, Input, Type};
+///
+/// let regex = create_reg_exp(Input::Maybe(Type::Digit)).unwrap();
+/// assert!(regex.is_match("1"));
+/// assert!(regex.is_match(""));
+/// assert!(regex.is_match("12"));
+/// assert!(regex.is_match("a"));
+/// assert!(regex.is_match("1 2"));
+/// ```
+pub enum Input<'a> {
+ OneOrMore(Type<'a>),
+ Exactly(Type<'a>),
+ Maybe(Type<'a>),
+ Times(Type<'a>, usize),
+}
+
+impl<'a> Display for Input<'a> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ const ESCAPE_REPLACE_RE: &str = r"[.*+?^${}()|[\\]\\/]";
+
+ let str = match self {
+ Input::OneOrMore(t) => format!("({}+)", t),
+ Input::Exactly(t) => match t {
+ Type::Text(t) => Regex::new(ESCAPE_REPLACE_RE)
+ .expect("Invalid replace_all regex")
+ .replace_all(t, r"\$0").parse().unwrap()
+ ,
+ _ => format!(r"\b{}\b", t),
+ },
+ Input::Maybe(t) => format!("({}?)", t),
+ Input::Times(t, n) => format!("{}{{{}}}", t, n),
+ };
+ write!(f, "{}", str)
+ }
+}
+
+impl<'a> AsRegex for Input<'a> {
+ fn as_regex(&self) -> Result<Regex> {
+ Ok(Regex::new(&self.to_string())?)
+ }
+}
+
+/// Returns a Regex, which chains the 2 given regexes with an `and` operator.
+///
+/// # Example
+/// ```
+/// use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase};
+///
+/// let regex = create_reg_exp(Exactly(Digit).or(Exactly(LetterLowercase))).unwrap();
+/// assert!(regex.is_match("1"));
+/// assert!(regex.is_match("a"));
+/// assert!(!regex.is_match("A"));
+/// assert!(!regex.is_match("12"));
+/// assert!(!regex.is_match("1a"));
+/// assert!(regex.is_match("1 a"));
+/// ```
+impl<'a> Condition for Input<'a> {}
+
+impl<'a> Input<'a> {
+ /// This defines the entire input so far as a named capture group.
+ ///
+ /// # Example
+ /// ```
+ /// use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase, OneOrMore};
+ ///
+ /// let regex = create_reg_exp(OneOrMore(Digit).grouped_as("digits")).unwrap();
+ /// assert_eq!(®ex.captures("1").unwrap()["digits"], "1");
+ /// ```
+ pub fn grouped_as(&self, name: &str) -> Regex {
+ Regex::new(&format!(r"(?P<{}>{})", name, self.to_string())).expect("Invalid regex")
+ }
+
+ /// This defines the entire input so far as a named capture group.
+ /// This is an alias for `grouped_as`.
+ pub fn r#as(&self, name: &str) -> Regex {
+ self.grouped_as(name)
+ }
+
+ /// This defines the entire input so far as an anonymous group.
+ ///
+ /// # Example
+ /// ```
+ /// use magic_regexp::{create_reg_exp, Condition, Exactly, Digit, LetterLowercase, OneOrMore, Type, Char, Whitespace, Maybe, Options};
+ /// use regex::Regex;
+ ///
+ /// let regex = create_reg_exp(OneOrMore(Digit).grouped()
+ /// .and(Exactly(Whitespace))
+ /// .and(OneOrMore(Char).or(Exactly(Whitespace)).optionally())
+ /// .and(OneOrMore(Digit).grouped())
+ /// ).unwrap();
+ /// assert_eq!(®ex.captures("1 5").unwrap()[1], "1");
+ /// assert_eq!(®ex.captures("134 23").unwrap()[1], "134");
+ /// // The folloing example is not really useful, because it shows only the first match.
+ /// // The second match is not captured. See the next example for a more useful example.
+ /// assert_eq!(®ex.captures("this is the 134 test 213").unwrap()[1], "134");
+ /// // This is a bit more complex, because we are using anonymous groups in regex.
+ /// let cap = ®ex
+ /// .find_iter("multiple numbers 134 2123")
+ /// .filter_map(|digits| digits.as_str().parse().ok())
+ /// .collect::<Vec<String>>()
+ /// .join(" ");
+ /// let expected = ["134", "2123"].join(" ");
+ /// assert_eq!(cap, &expected);
+ /// ```
+ ///
+ pub fn grouped(&self) -> Regex {
+ Regex::new(&format!(r"({})", self.to_string())).expect("Invalid regex")
+ }
+}
+
+impl AsRegex for Regex {}
+
+impl Condition for Regex {}
+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +
/*!
+This crate provides a library for creating regular expressions in a more readable way.
+It stands on the shoulders of the [regex](https://crates.io/crates/regex) crate.
+
+For more specific details on the API for regular expressions, please see around the enums in the left sidebar.
+
+# Example: Find a date
+
+```rust
+use magic_regexp::{Digit, Times, create_reg_exp, Exactly, Condition, Text};
+use regex::Regex;
+
+const TO_SEARCH: &'static str = "On 2010-03-14, foo happened. On 2014-10-14, bar happened.";
+let input = Times(Digit, 4).and(Exactly(Text("-"))).and(Times(Digit, 2)).and(Exactly(Text(("-")))).and(Times(Digit, 2));
+assert_eq!(input.to_string(), r"\d{4}-\d{2}-\d{2}");
+
+let input = Times(Digit, 4).grouped_as("year").and(Exactly(Text("-"))).and(Times(Digit, 2).grouped_as("month")).and(Exactly(Text(("-")))).and(Times(Digit, 2).grouped_as("day"));
+let re = create_reg_exp(input).unwrap();
+assert!(re.is_match("2014-01-01"));
+assert_eq!(re.find_iter(TO_SEARCH).count(), 2);
+
+for caps in re.captures_iter(TO_SEARCH) {
+ // Note that all of the unwraps are actually OK for this regex
+ // because the only way for the regex to match is if all of the
+ // capture groups match. This is not true in general though!
+ println!("year: {}, month: {}, day: {}",
+ caps.get(1).unwrap().as_str(),
+ caps.get(2).unwrap().as_str(),
+ caps.get(3).unwrap().as_str());
+}
+```
+*/
+
+mod core;
+pub use crate::core::*;
+
+use regex::Regex;
+
+/// Returns the regex, which represents the given statement.
+/// This is only for convenience and compatibility with magic-regex from npm.
+///
+/// # Example
+/// ```
+/// use magic_regexp::{Digit, Times, create_reg_exp, Exactly, Condition, Text};
+/// use regex::Regex;
+///
+/// const TO_SEARCH: &'static str = "On 2010-03-14, foo happened. On 2014-10-14, bar happened.";
+/// let input = Times(Digit, 4).and(Exactly(Text("-"))).and(Times(Digit, 2)).and(Exactly(Text(("-")))).and(Times(Digit, 2));
+/// assert_eq!(input.to_string(), r"\d{4}-\d{2}-\d{2}");
+/// let input = Times(Digit, 4).grouped_as("year").and(Exactly(Text("-"))).and(Times(Digit, 2).grouped_as("month")).and(Exactly(Text(("-")))).and(Times(Digit, 2).grouped_as("day"));
+/// let re = create_reg_exp(input).unwrap();
+/// assert!(re.is_match("2014-01-01"));
+/// assert_eq!(re.find_iter(TO_SEARCH).count(), 2);
+/// for caps in re.captures_iter(TO_SEARCH) {
+/// // Note that all of the unwraps are actually OK for this regex
+/// // because the only way for the regex to match is if all of the
+/// // capture groups match. This is not true in general though!
+/// println!("year: {}, month: {}, day: {}",
+/// caps.get(1).unwrap().as_str(),
+/// caps.get(2).unwrap().as_str(),
+/// caps.get(3).unwrap().as_str());
+/// }
+/// ```
+pub fn create_reg_exp(input: impl AsRegex) -> Result<Regex> {
+ input.as_regex()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{create_reg_exp, not, Exactly, OneOrMore, Type::Digit};
+ use crate::Input::Maybe;
+ use crate::Type::Text;
+
+ #[test]
+ fn test_single_digit() {
+ let input = Exactly(Digit);
+ let regex = create_reg_exp(input).unwrap();
+ assert!(regex.is_match("1"));
+ assert!(!regex.is_match("12"));
+ assert!(regex.is_match("1 2"));
+ }
+
+ #[test]
+ fn test_maybe_digit() {
+ let input = Maybe(Digit);
+ let regex = create_reg_exp(input).unwrap();
+ assert!(regex.is_match("1"));
+ assert!(regex.is_match(""));
+ assert!(regex.is_match("12"));
+ assert!(regex.is_match("1 2"));
+ }
+ #[test]
+ fn test_one_or_more_digits() {
+ let input = OneOrMore(Digit);
+ let regex = create_reg_exp(input).unwrap();
+ assert!(regex.is_match("1"));
+ assert!(regex.is_match("12"));
+ assert!(regex.is_match("1 2"));
+ assert!(regex.is_match("123"));
+ assert!(regex.is_match("12a3"));
+ }
+
+ #[test]
+ fn test_not_digit() {
+ let input = Exactly(not(Digit));
+ let regex = create_reg_exp(input).unwrap();
+ assert!(!regex.is_match("1"));
+ assert!(regex.is_match("a"));
+ }
+
+ #[test]
+ fn test_not_not_stuff() {
+ let input = Exactly(not(not(Digit)));
+ let regex = create_reg_exp(input).unwrap();
+ assert!(regex.is_match("1"));
+ assert!(!regex.is_match("a"));
+ }
+
+ #[test]
+ fn test_exactly_text() {
+ let input = Exactly(Text("welt".into()));
+ let regex = create_reg_exp(input).unwrap();
+ assert!(regex.is_match("Hallo welt"));
+ assert!(!regex.is_match("Hallo Welt"));
+ }
+}
+
fn:
) to \
+ restrict the search to a given item kind.","Accepted kinds are: fn
, mod
, struct
, \
+ enum
, trait
, type
, macro
, \
+ and const
.","Search functions by type signature (e.g., vec -> usize
or \
+ -> vec
or String, enum:Cow -> bool
)","You can look for items with an exact name by putting double quotes around \
+ your request: \"string\"
","Look for functions that accept or return \
+ slices and \
+ arrays by writing \
+ square brackets (e.g., -> [u8]
or [] -> Option
)","Look for items inside another one by searching for a path: vec::Vec
",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}
`}else{error[index]=value}});output+=`Takes each element in the Iterator
: if it is an Err
, no further\nelements are taken, and the Err
is returned. Should no Err
occur, a\ncontainer with the values of each Result
is returned.
Here is an example which increments every integer in a vector,\nchecking for overflow:
\n\nlet v = vec![1, 2];\nlet res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|\n x.checked_add(1).ok_or(\"Overflow!\")\n).collect();\nassert_eq!(res, Ok(vec![2, 3]));
Here is another example that tries to subtract one from another list\nof integers, this time checking for underflow:
\n\nlet v = vec![1, 2, 0];\nlet res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|\n x.checked_sub(1).ok_or(\"Underflow!\")\n).collect();\nassert_eq!(res, Err(\"Underflow!\"));
Here is a variation on the previous example, showing that no\nfurther elements are taken from iter
after the first Err
.
let v = vec![3, 2, 1, 10];\nlet mut shared = 0;\nlet res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32| {\n shared += x;\n x.checked_sub(2).ok_or(\"Underflow!\")\n}).collect();\nassert_eq!(res, Err(\"Underflow!\"));\nassert_eq!(shared, 6);
Since the third element caused an underflow, no further elements were taken,\nso the final value of shared
is 6 (= 3 + 2 + 1
), not 16.
try_trait_v2
)Residual
type. Read moreReturns a consuming iterator over the possibly contained value.
\nThe iterator yields one value if the result is Result::Ok
, otherwise none.
let x: Result<u32, &str> = Ok(5);\nlet v: Vec<u32> = x.into_iter().collect();\nassert_eq!(v, [5]);\n\nlet x: Result<u32, &str> = Err(\"nothing!\");\nlet v: Vec<u32> = x.into_iter().collect();\nassert_eq!(v, []);
self
and other
) and is used by the <=
\noperator. Read moreTakes each element in the Iterator
: if it is an Err
, no further\nelements are taken, and the Err
is returned. Should no Err
\noccur, the product of all elements is returned.
This multiplies each number in a vector of strings,\nif a string could not be parsed the operation returns Err
:
let nums = vec![\"5\", \"10\", \"1\", \"2\"];\nlet total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();\nassert_eq!(total, Ok(100));\nlet nums = vec![\"5\", \"10\", \"one\", \"2\"];\nlet total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();\nassert!(total.is_err());
Maps a Result<&mut T, E>
to a Result<T, E>
by copying the contents of the\nOk
part.
let mut val = 12;\nlet x: Result<&mut i32, i32> = Ok(&mut val);\nassert_eq!(x, Ok(&mut 12));\nlet copied = x.copied();\nassert_eq!(copied, Ok(12));
Maps a Result<&mut T, E>
to a Result<T, E>
by cloning the contents of the\nOk
part.
let mut val = 12;\nlet x: Result<&mut i32, i32> = Ok(&mut val);\nassert_eq!(x, Ok(&mut 12));\nlet cloned = x.cloned();\nassert_eq!(cloned, Ok(12));
Transposes a Result
of an Option
into an Option
of a Result
.
Ok(None)
will be mapped to None
.\nOk(Some(_))
and Err(_)
will be mapped to Some(Ok(_))
and Some(Err(_))
.
#[derive(Debug, Eq, PartialEq)]\nstruct SomeErr;\n\nlet x: Result<Option<i32>, SomeErr> = Ok(Some(5));\nlet y: Option<Result<i32, SomeErr>> = Some(Ok(5));\nassert_eq!(x.transpose(), y);
result_flattening
)Converts from Result<Result<T, E>, E>
to Result<T, E>
#![feature(result_flattening)]\nlet x: Result<Result<&'static str, u32>, u32> = Ok(Ok(\"hello\"));\nassert_eq!(Ok(\"hello\"), x.flatten());\n\nlet x: Result<Result<&'static str, u32>, u32> = Ok(Err(6));\nassert_eq!(Err(6), x.flatten());\n\nlet x: Result<Result<&'static str, u32>, u32> = Err(6);\nassert_eq!(Err(6), x.flatten());
Flattening only removes one level of nesting at a time:
\n\n#![feature(result_flattening)]\nlet x: Result<Result<Result<&'static str, u32>, u32>, u32> = Ok(Ok(Ok(\"hello\")));\nassert_eq!(Ok(Ok(\"hello\")), x.flatten());\nassert_eq!(Ok(\"hello\"), x.flatten().flatten());
Returns true
if the result is Ok
and the value inside of it matches a predicate.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(x.is_ok_and(|x| x > 1), true);\n\nlet x: Result<u32, &str> = Ok(0);\nassert_eq!(x.is_ok_and(|x| x > 1), false);\n\nlet x: Result<u32, &str> = Err(\"hey\");\nassert_eq!(x.is_ok_and(|x| x > 1), false);
Returns true
if the result is Err
and the value inside of it matches a predicate.
use std::io::{Error, ErrorKind};\n\nlet x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, \"!\"));\nassert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), true);\n\nlet x: Result<u32, Error> = Err(Error::new(ErrorKind::PermissionDenied, \"!\"));\nassert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);\n\nlet x: Result<u32, Error> = Ok(123);\nassert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);
Converts from Result<T, E>
to Option<E>
.
Converts self
into an Option<E>
, consuming self
,\nand discarding the success value, if any.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(x.err(), None);\n\nlet x: Result<u32, &str> = Err(\"Nothing here\");\nassert_eq!(x.err(), Some(\"Nothing here\"));
Converts from &Result<T, E>
to Result<&T, &E>
.
Produces a new Result
, containing a reference\ninto the original, leaving the original in place.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(x.as_ref(), Ok(&2));\n\nlet x: Result<u32, &str> = Err(\"Error\");\nassert_eq!(x.as_ref(), Err(&\"Error\"));
Converts from &mut Result<T, E>
to Result<&mut T, &mut E>
.
fn mutate(r: &mut Result<i32, i32>) {\n match r.as_mut() {\n Ok(v) => *v = 42,\n Err(e) => *e = 0,\n }\n}\n\nlet mut x: Result<i32, i32> = Ok(2);\nmutate(&mut x);\nassert_eq!(x.unwrap(), 42);\n\nlet mut x: Result<i32, i32> = Err(13);\nmutate(&mut x);\nassert_eq!(x.unwrap_err(), 0);
Maps a Result<T, E>
to Result<U, E>
by applying a function to a\ncontained Ok
value, leaving an Err
value untouched.
This function can be used to compose the results of two functions.
\nPrint the numbers on each line of a string multiplied by two.
\n\nlet line = \"1\\n2\\n3\\n4\\n\";\n\nfor num in line.lines() {\n match num.parse::<i32>().map(|i| i * 2) {\n Ok(n) => println!(\"{n}\"),\n Err(..) => {}\n }\n}
Returns the provided default (if Err
), or\napplies a function to the contained value (if Ok
).
Arguments passed to map_or
are eagerly evaluated; if you are passing\nthe result of a function call, it is recommended to use map_or_else
,\nwhich is lazily evaluated.
let x: Result<_, &str> = Ok(\"foo\");\nassert_eq!(x.map_or(42, |v| v.len()), 3);\n\nlet x: Result<&str, _> = Err(\"bar\");\nassert_eq!(x.map_or(42, |v| v.len()), 42);
Maps a Result<T, E>
to U
by applying fallback function default
to\na contained Err
value, or function f
to a contained Ok
value.
This function can be used to unpack a successful result\nwhile handling an error.
\nlet k = 21;\n\nlet x : Result<_, &str> = Ok(\"foo\");\nassert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 3);\n\nlet x : Result<&str, _> = Err(\"bar\");\nassert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 42);
Maps a Result<T, E>
to Result<T, F>
by applying a function to a\ncontained Err
value, leaving an Ok
value untouched.
This function can be used to pass through a successful result while handling\nan error.
\nfn stringify(x: u32) -> String { format!(\"error code: {x}\") }\n\nlet x: Result<u32, u32> = Ok(2);\nassert_eq!(x.map_err(stringify), Ok(2));\n\nlet x: Result<u32, u32> = Err(13);\nassert_eq!(x.map_err(stringify), Err(\"error code: 13\".to_string()));
Converts from Result<T, E>
(or &Result<T, E>
) to Result<&<T as Deref>::Target, &E>
.
Coerces the Ok
variant of the original Result
via Deref
\nand returns the new Result
.
let x: Result<String, u32> = Ok(\"hello\".to_string());\nlet y: Result<&str, &u32> = Ok(\"hello\");\nassert_eq!(x.as_deref(), y);\n\nlet x: Result<String, u32> = Err(42);\nlet y: Result<&str, &u32> = Err(&42);\nassert_eq!(x.as_deref(), y);
Converts from Result<T, E>
(or &mut Result<T, E>
) to Result<&mut <T as DerefMut>::Target, &mut E>
.
Coerces the Ok
variant of the original Result
via DerefMut
\nand returns the new Result
.
let mut s = \"HELLO\".to_string();\nlet mut x: Result<String, u32> = Ok(\"hello\".to_string());\nlet y: Result<&mut str, &mut u32> = Ok(&mut s);\nassert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);\n\nlet mut i = 42;\nlet mut x: Result<String, u32> = Err(42);\nlet y: Result<&mut str, &mut u32> = Err(&mut i);\nassert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
Returns an iterator over the possibly contained value.
\nThe iterator yields one value if the result is Result::Ok
, otherwise none.
let x: Result<u32, &str> = Ok(7);\nassert_eq!(x.iter().next(), Some(&7));\n\nlet x: Result<u32, &str> = Err(\"nothing!\");\nassert_eq!(x.iter().next(), None);
Returns a mutable iterator over the possibly contained value.
\nThe iterator yields one value if the result is Result::Ok
, otherwise none.
let mut x: Result<u32, &str> = Ok(7);\nmatch x.iter_mut().next() {\n Some(v) => *v = 40,\n None => {},\n}\nassert_eq!(x, Ok(40));\n\nlet mut x: Result<u32, &str> = Err(\"nothing!\");\nassert_eq!(x.iter_mut().next(), None);
Returns the contained Ok
value, consuming the self
value.
Because this function may panic, its use is generally discouraged.\nInstead, prefer to use pattern matching and handle the Err
\ncase explicitly, or call unwrap_or
, unwrap_or_else
, or\nunwrap_or_default
.
Panics if the value is an Err
, with a panic message including the\npassed message, and the content of the Err
.
let x: Result<u32, &str> = Err(\"emergency failure\");\nx.expect(\"Testing expect\"); // panics with `Testing expect: emergency failure`
We recommend that expect
messages are used to describe the reason you\nexpect the Result
should be Ok
.
let path = std::env::var(\"IMPORTANT_PATH\")\n .expect(\"env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`\");
Hint: If you’re having trouble remembering how to phrase expect\nerror messages remember to focus on the word “should” as in “env\nvariable should be set by blah” or “the given binary should be available\nand executable by the current user”.
\nFor more detail on expect message styles and the reasoning behind our recommendation please\nrefer to the section on “Common Message\nStyles” in the\nstd::error
module docs.
Returns the contained Ok
value, consuming the self
value.
Because this function may panic, its use is generally discouraged.\nInstead, prefer to use pattern matching and handle the Err
\ncase explicitly, or call unwrap_or
, unwrap_or_else
, or\nunwrap_or_default
.
Panics if the value is an Err
, with a panic message provided by the\nErr
’s value.
Basic usage:
\n\nlet x: Result<u32, &str> = Ok(2);\nassert_eq!(x.unwrap(), 2);
let x: Result<u32, &str> = Err(\"emergency failure\");\nx.unwrap(); // panics with `emergency failure`
Returns the contained Ok
value or a default
Consumes the self
argument then, if Ok
, returns the contained\nvalue, otherwise if Err
, returns the default value for that\ntype.
Converts a string to an integer, turning poorly-formed strings\ninto 0 (the default value for integers). parse
converts\na string to any other type that implements FromStr
, returning an\nErr
on error.
let good_year_from_input = \"1909\";\nlet bad_year_from_input = \"190blarg\";\nlet good_year = good_year_from_input.parse().unwrap_or_default();\nlet bad_year = bad_year_from_input.parse().unwrap_or_default();\n\nassert_eq!(1909, good_year);\nassert_eq!(0, bad_year);
Returns the contained Err
value, consuming the self
value.
Panics if the value is an Ok
, with a panic message including the\npassed message, and the content of the Ok
.
let x: Result<u32, &str> = Ok(10);\nx.expect_err(\"Testing expect_err\"); // panics with `Testing expect_err: 10`
Returns the contained Err
value, consuming the self
value.
Panics if the value is an Ok
, with a custom panic message provided\nby the Ok
’s value.
let x: Result<u32, &str> = Ok(2);\nx.unwrap_err(); // panics with `2`
let x: Result<u32, &str> = Err(\"emergency failure\");\nassert_eq!(x.unwrap_err(), \"emergency failure\");
unwrap_infallible
)Returns the contained Ok
value, but never panics.
Unlike unwrap
, this method is known to never panic on the\nresult types it is implemented for. Therefore, it can be used\ninstead of unwrap
as a maintainability safeguard that will fail\nto compile if the error type of the Result
is later changed\nto an error that can actually occur.
\nfn only_good_news() -> Result<String, !> {\n Ok(\"this is fine\".into())\n}\n\nlet s: String = only_good_news().into_ok();\nprintln!(\"{s}\");
unwrap_infallible
)Returns the contained Err
value, but never panics.
Unlike unwrap_err
, this method is known to never panic on the\nresult types it is implemented for. Therefore, it can be used\ninstead of unwrap_err
as a maintainability safeguard that will fail\nto compile if the ok type of the Result
is later changed\nto a type that can actually occur.
\nfn only_bad_news() -> Result<!, String> {\n Err(\"Oops, it failed\".into())\n}\n\nlet error: String = only_bad_news().into_err();\nprintln!(\"{error}\");
Returns res
if the result is Ok
, otherwise returns the Err
value of self
.
Arguments passed to and
are eagerly evaluated; if you are passing the\nresult of a function call, it is recommended to use and_then
, which is\nlazily evaluated.
let x: Result<u32, &str> = Ok(2);\nlet y: Result<&str, &str> = Err(\"late error\");\nassert_eq!(x.and(y), Err(\"late error\"));\n\nlet x: Result<u32, &str> = Err(\"early error\");\nlet y: Result<&str, &str> = Ok(\"foo\");\nassert_eq!(x.and(y), Err(\"early error\"));\n\nlet x: Result<u32, &str> = Err(\"not a 2\");\nlet y: Result<&str, &str> = Err(\"late error\");\nassert_eq!(x.and(y), Err(\"not a 2\"));\n\nlet x: Result<u32, &str> = Ok(2);\nlet y: Result<&str, &str> = Ok(\"different result type\");\nassert_eq!(x.and(y), Ok(\"different result type\"));
Calls op
if the result is Ok
, otherwise returns the Err
value of self
.
This function can be used for control flow based on Result
values.
fn sq_then_to_string(x: u32) -> Result<String, &'static str> {\n x.checked_mul(x).map(|sq| sq.to_string()).ok_or(\"overflowed\")\n}\n\nassert_eq!(Ok(2).and_then(sq_then_to_string), Ok(4.to_string()));\nassert_eq!(Ok(1_000_000).and_then(sq_then_to_string), Err(\"overflowed\"));\nassert_eq!(Err(\"not a number\").and_then(sq_then_to_string), Err(\"not a number\"));
Often used to chain fallible operations that may return Err
.
use std::{io::ErrorKind, path::Path};\n\n// Note: on Windows \"/\" maps to \"C:\\\"\nlet root_modified_time = Path::new(\"/\").metadata().and_then(|md| md.modified());\nassert!(root_modified_time.is_ok());\n\nlet should_fail = Path::new(\"/bad/path\").metadata().and_then(|md| md.modified());\nassert!(should_fail.is_err());\nassert_eq!(should_fail.unwrap_err().kind(), ErrorKind::NotFound);
Returns res
if the result is Err
, otherwise returns the Ok
value of self
.
Arguments passed to or
are eagerly evaluated; if you are passing the\nresult of a function call, it is recommended to use or_else
, which is\nlazily evaluated.
let x: Result<u32, &str> = Ok(2);\nlet y: Result<u32, &str> = Err(\"late error\");\nassert_eq!(x.or(y), Ok(2));\n\nlet x: Result<u32, &str> = Err(\"early error\");\nlet y: Result<u32, &str> = Ok(2);\nassert_eq!(x.or(y), Ok(2));\n\nlet x: Result<u32, &str> = Err(\"not a 2\");\nlet y: Result<u32, &str> = Err(\"late error\");\nassert_eq!(x.or(y), Err(\"late error\"));\n\nlet x: Result<u32, &str> = Ok(2);\nlet y: Result<u32, &str> = Ok(100);\nassert_eq!(x.or(y), Ok(2));
Calls op
if the result is Err
, otherwise returns the Ok
value of self
.
This function can be used for control flow based on result values.
\nfn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }\nfn err(x: u32) -> Result<u32, u32> { Err(x) }\n\nassert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));\nassert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2));\nassert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));\nassert_eq!(Err(3).or_else(err).or_else(err), Err(3));
Returns the contained Ok
value or a provided default.
Arguments passed to unwrap_or
are eagerly evaluated; if you are passing\nthe result of a function call, it is recommended to use unwrap_or_else
,\nwhich is lazily evaluated.
let default = 2;\nlet x: Result<u32, &str> = Ok(9);\nassert_eq!(x.unwrap_or(default), 9);\n\nlet x: Result<u32, &str> = Err(\"error\");\nassert_eq!(x.unwrap_or(default), default);
Returns the contained Ok
value, consuming the self
value,\nwithout checking that the value is not an Err
.
Calling this method on an Err
is undefined behavior.
let x: Result<u32, &str> = Ok(2);\nassert_eq!(unsafe { x.unwrap_unchecked() }, 2);
let x: Result<u32, &str> = Err(\"emergency failure\");\nunsafe { x.unwrap_unchecked(); } // Undefined behavior!
Returns the contained Err
value, consuming the self
value,\nwithout checking that the value is not an Ok
.
Calling this method on an Ok
is undefined behavior.
let x: Result<u32, &str> = Ok(2);\nunsafe { x.unwrap_err_unchecked() }; // Undefined behavior!
let x: Result<u32, &str> = Err(\"emergency failure\");\nassert_eq!(unsafe { x.unwrap_err_unchecked() }, \"emergency failure\");
Takes each element in the Iterator
: if it is an Err
, no further\nelements are taken, and the Err
is returned. Should no Err
\noccur, the sum of all elements is returned.
This sums up every integer in a vector, rejecting the sum if a negative\nelement is encountered:
\n\nlet f = |&x: &i32| if x < 0 { Err(\"Negative element found\") } else { Ok(x) };\nlet v = vec![1, 2];\nlet res: Result<i32, _> = v.iter().map(f).sum();\nassert_eq!(res, Ok(3));\nlet v = vec![1, -2];\nlet res: Result<i32, _> = v.iter().map(f).sum();\nassert_eq!(res, Err(\"Negative element found\"));
try_trait_v2
)?
when not short-circuiting.try_trait_v2
)FromResidual::from_residual
\nas part of ?
when short-circuiting. Read moretry_trait_v2
)Output
type. Read moretry_trait_v2
)?
to decide whether the operator should produce a value\n(because this returned ControlFlow::Continue
)\nor propagate a value back to the caller\n(because this returned ControlFlow::Break
). Read more