Skip to content

Commit 6b94f49

Browse files
authored
Merge pull request #11 from popzxc/new-things
Add a bunch of new macros
2 parents 9caa826 + fbb0ecb commit 6b94f49

File tree

5 files changed

+167
-5
lines changed

5 files changed

+167
-5
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## [[Unreleased]]
44

5+
- `try_match` and `unwrap_match` macros to get a certain variant from an enum.
6+
- `return_ok` and `return_some` macros for early return of successful calculation.
7+
58
## 0.2.1 (09.07.2020)
69

710
- `VecExt::remove_item` method was added (#9).

src/duration.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,8 @@ mod tests {
302302
.add_days(1);
303303

304304
let expected_duration = Duration::new(
305-
1 * SECS_IN_DAY + 1 * SECS_IN_HOUR + 1 * SECS_IN_MIN + 1,
306-
1 * 1_000_000 + 1 * 1_000 + 1,
305+
SECS_IN_DAY + SECS_IN_HOUR + SECS_IN_MIN + 1,
306+
1_000_000 + 1_000 + 1,
307307
);
308308

309309
assert_eq!(duration, expected_duration);

src/macros.rs

+160-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ macro_rules! compile_warning {
4343
/// As the internal implementation is based on the [`std::any::type_name`], this macro derives
4444
/// all the limitations of this function.
4545
///
46-
/// # Examples
46+
/// ## Examples
4747
///
4848
/// ```rust
4949
/// mod bar {
@@ -70,3 +70,162 @@ macro_rules! function_name {
7070
&name[..name.len() - 3]
7171
}};
7272
}
73+
74+
/// Attempts to get variant from the enum variable.
75+
///
76+
/// ## Examples
77+
///
78+
/// ```rust
79+
/// # use stdext::try_match;
80+
///
81+
/// #[derive(Debug, PartialEq)]
82+
/// enum Foo {
83+
/// Left(u16),
84+
/// Right(&'static str),
85+
/// }
86+
///
87+
/// assert_eq!(try_match!(Foo::Left(18), Foo::Left), Ok(18));
88+
/// assert_eq!(
89+
/// try_match!(Foo::Right("nope"), Foo::Left),
90+
/// Err(Foo::Right("nope"))
91+
/// );
92+
/// ```
93+
#[macro_export]
94+
macro_rules! try_match {
95+
($var:expr, $variant:path) => {
96+
if let $variant(x) = $var {
97+
Ok(x)
98+
} else {
99+
Err($var)
100+
}
101+
};
102+
}
103+
104+
/// Similar to [`try_match`] but additionally unwraps the result.
105+
///
106+
/// ## Panics
107+
///
108+
/// Panics if expression didn't match the provided path.
109+
///
110+
/// ## Examples
111+
///
112+
/// ```rust
113+
/// # use stdext::unwrap_match;
114+
///
115+
/// #[derive(Debug, PartialEq)]
116+
/// enum Foo {
117+
/// Left(u16),
118+
/// Right(&'static str),
119+
/// }
120+
///
121+
/// assert_eq!(unwrap_match!(Foo::Left(18), Foo::Left), 18);
122+
/// ```
123+
///
124+
/// The following example will panic:
125+
///
126+
/// ```should_panic
127+
/// # use stdext::unwrap_match;
128+
/// # #[derive(Debug, PartialEq)]
129+
/// # enum Foo {
130+
/// # Left(u16),
131+
/// # Right(&'static str),
132+
/// # }
133+
/// assert_eq!(unwrap_match!(Foo::Right("nope"), Foo::Left), 18);
134+
/// ```
135+
#[macro_export]
136+
macro_rules! unwrap_match {
137+
($var:expr, $variant:path) => {
138+
$crate::try_match!($var, $variant).unwrap()
139+
};
140+
}
141+
142+
/// Checks whether supplied [`Result`] variable is `Ok`
143+
/// and if so, returns it.
144+
///
145+
/// If variant is an `Err`, macro evaluates to the contents of the `Err`
146+
/// variant.
147+
///
148+
/// This macro supports two forms:
149+
/// - `return_ok!(Ok(42));` - will return `Ok(42)`.
150+
/// - `return_ok!(inner Ok(42));` - will return just `42`.
151+
///
152+
/// ## Examples
153+
///
154+
/// ```rust
155+
/// # use stdext::return_ok;
156+
///
157+
/// fn choose_one(left: Result<u8, ()>, right: Result<u8, ()>) -> Result<u8, ()> {
158+
/// return_ok!(left);
159+
/// return_ok!(right);
160+
/// Err(())
161+
/// }
162+
///
163+
/// fn choose_one_inner(left: Result<u8, ()>, right: Result<u8, ()>) -> u8 {
164+
/// return_ok!(inner left);
165+
/// return_ok!(inner right);
166+
/// panic!("Both variables are bad")
167+
/// }
168+
///
169+
/// assert_eq!(choose_one(Err(()), Ok(10)), Ok(10));
170+
/// assert_eq!(choose_one_inner(Ok(1), Err(())), 1);
171+
/// ```
172+
#[macro_export]
173+
macro_rules! return_ok {
174+
($var:expr) => {
175+
match $var {
176+
Ok(val) => return Ok(val),
177+
Err(err) => err,
178+
}
179+
};
180+
(inner $var:expr) => {
181+
match $var {
182+
Ok(val) => return val,
183+
Err(err) => err,
184+
}
185+
};
186+
}
187+
188+
/// Checks whether supplied [`Option`] variable is `Some`
189+
/// and if so, returns it.
190+
///
191+
/// If variant is an `None`, nothing happens.
192+
///
193+
/// This macro supports two forms:
194+
/// - `return_some!(Some(42));` - will return `Some(42)`.
195+
/// - `return_some!(inner Some(42));` - will return just `42`.
196+
///
197+
/// ## Examples
198+
///
199+
/// ```rust
200+
/// # use stdext::return_some;
201+
///
202+
/// fn choose_one(left: Option<u8>, right: Option<u8>) -> Option<u8> {
203+
/// return_some!(left);
204+
/// return_some!(right);
205+
/// None
206+
/// }
207+
///
208+
/// fn choose_one_inner(left: Option<u8>, right: Option<u8>) -> u8 {
209+
/// return_some!(inner left);
210+
/// return_some!(inner right);
211+
/// panic!("Both variables are bad")
212+
/// }
213+
///
214+
/// assert_eq!(choose_one(None, Some(10)), Some(10));
215+
/// assert_eq!(choose_one_inner(Some(1), None), 1);
216+
/// ```
217+
#[macro_export]
218+
macro_rules! return_some {
219+
($var:expr) => {
220+
match $var {
221+
Some(val) => return Some(val),
222+
None => {}
223+
}
224+
};
225+
(inner $var:expr) => {
226+
match $var {
227+
Some(val) => return val,
228+
None => {}
229+
}
230+
};
231+
}

src/option.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ mod tests {
107107
fn combine_with() {
108108
fn f(l: i32, r: i32) -> i32 {
109109
l + r
110-
};
110+
}
111111

112112
// Test vector of (left, right, expected) values.
113113
let test_vector = vec![

src/result.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ mod tests {
9595
fn combine_with() {
9696
fn f(l: i32, r: i32) -> i32 {
9797
l + r
98-
};
98+
}
9999

100100
// Test vector of (left, right, expected) values.
101101
let test_vector = vec![

0 commit comments

Comments
 (0)