libsugar/lib.rs
1//! libsugar provides syntactic sugar in the form of a library
2//!
3//! ## Features
4//!
5//! default = `["std", "combin", "named-into", "macro-lit", "side-effect", "re-exports", "chain_panic", "chain_todo", "tuples", "once_get", "chain_drop"]`
6//!
7//! - `"std"` Enable std
8//! - `"side-effect"` Enable mod [side_effect](side_effect/index.html)
9//! - `"named-into"` Enable mod [named_into](named_into/index.html)
10//! - `"combin"` Enable mod [combin](combin/index.html)
11//! - `"macro-lit"` Enable macro like [new](macro.new.html), [list](macro.list.html)
12//! - `"chain_panic"` Enable mod [chain_panic](chain_panic/index.html)
13//! - `"chain_todo"` Enable mod [chain_todo](chain_todo/index.html)
14//! - `"chain_drop"` Enable mod [chain_drop](chain_drop/index.html)
15//! - `"tuples"` Enable mod [tuples](tuples/index.html)
16//! - `"once_get"` Enable mod [once_get](once_get/index.html)
17//! - `"re-exports"` Enable re-export of all mods
18//!
19
20#![cfg_attr(not(feature = "std"), no_std)]
21
22#[doc(hidden)]
23#[macro_export]
24macro_rules! _matchand {
25 { ; $b:block $($el:block)? } => { $b };
26 { $p:pat = $e:expr; { } $($pp:pat = $ee:expr; { })+ ; $b:block $($el:block)?} => {
27 if let $p = $e { _matchand!($($pp = $ee ; {})* ; $b $($el)?) } $(else $el)?
28 };
29 { $p:pat = $e:expr; { } ; $b:block $($el:block)? } => { if let $p = $e $b $(else $el)? };
30}
31#[doc(hidden)]
32#[macro_export]
33macro_rules! _select_op {
34 { $x:expr ; $op:tt $a:expr } => { $x $op $a };
35 { $x:expr ; $op:tt $a:expr ; ! } => { $a $op $x };
36}
37/// batch opers
38/// ## Usage
39/// - **Basic**
40/// - batch `||`
41/// ```rust
42/// # use libsugar::*;
43/// # let v =
44/// bop!(|| 4; == 2, > 3);
45/// # assert!(v);
46/// ```
47/// *equivalent to*
48/// ```rust
49/// # let v =
50/// 4 == 2 || 4 > 3;
51/// # assert!(v);
52/// ```
53/// - batch `&&`
54/// ```rust
55/// # use libsugar::*;
56/// # let v =
57/// bop!(&& 4; == 2, > 3);
58/// # assert!(!v);
59/// ```
60/// *equivalent to*
61/// ```rust
62/// # let v =
63/// 4 == 2 && 4 > 3;
64/// # assert!(!v);
65/// ```
66/// - `!`
67/// ```rust
68/// # use libsugar::*;
69/// # let a = 1;
70/// # let v =
71/// bop!(|| a; == 1;!, == 2);
72/// # assert!(v);
73/// ```
74/// *equivalent to*
75/// ```rust
76/// # let a = 1;
77/// # let v =
78/// 1 == a || a == 2
79/// # ;
80/// # assert!(v);
81/// ```
82/// - batch op
83/// ```rust
84/// # use libsugar::*;
85/// # let v =
86/// bop!(&& 5; > ; 2, 3, 6;!);
87/// # assert!(v);
88/// ```
89/// *equivalent to*
90/// ```rust
91/// # let v =
92/// 5 > 2 && 5 > 3 && 6 > 5;
93/// # assert!(v);
94/// ```
95/// - **Set**
96/// ```rust
97/// # use libsugar::*;
98/// let mut a = 1;
99/// bop!(= a; + 1, - 2;!, * 3);
100/// # assert_eq!(a, 0);
101/// ```
102/// *equivalent to*
103/// ```rust
104/// let mut a = 1;
105/// a = a + 1;
106/// a = 2 - a;
107/// a = a * 3;
108/// # assert_eq!(a, 0);
109/// ```
110/// - **Let**
111/// ```rust
112/// # use libsugar::*;
113/// bop! { let a|u8 = 1, mut b = 2 }
114/// # assert_eq!(a, 1);
115/// # assert_eq!(b, 2);
116/// ```
117/// *equivalent to*
118/// ```no_run
119/// let a: u8 = 1;
120/// let mut b = 2;
121/// ```
122/// - **Let chain**
123/// - basic
124/// ```rust
125/// # use libsugar::*;
126/// let a = Some(1);
127/// let b = Some(2);
128///
129/// let v: i32 = bop!(match && Some(va) = a, Some(vb) = b => {
130/// 1
131/// } else {
132/// 2
133/// });
134/// # assert_eq!(v, 1);
135/// ```
136/// *equivalent to*
137/// ```rust
138/// let a = Some(1);
139/// let b = Some(2);
140///
141/// let v: i32 = loop {
142/// if let Some(va) = a {
143/// if let Some(vb) = b {
144/// break { 1 };
145/// }
146/// }
147/// break { 2 };
148/// };
149/// # assert_eq!(v, 1);
150/// ```
151/// - `bool`
152/// ```rust
153/// # use libsugar::*;
154/// # let a = Some(1);
155/// # let b = Some(2);
156/// let v: bool = bop!(bool match && Some(va) = a, Some(vb) = b => {
157/// 1
158/// } else {
159/// 2
160/// });
161/// # assert!(v);
162/// ```
163/// *equivalent to*
164/// ```rust
165/// # let a = Some(1);
166/// # let b = Some(2);
167/// let v: bool = loop {
168/// if let Some(va) = a {
169/// if let Some(vb) = b {
170/// { 1 };
171/// break true;
172/// }
173/// }
174/// { 2 };
175/// break false;
176/// };
177/// # assert!(v);
178/// ```
179/// - `!loop`
180/// ```rust
181/// # use libsugar::*;
182/// # let a = Some(1);
183/// # let b = Some(2);
184/// let v: i32 = bop!(!loop match && Some(va) = a, Some(vb) = b => {
185/// 1
186/// } else {
187/// 2
188/// });
189/// # assert_eq!(v, 1)
190/// ```
191/// *equivalent to*
192/// ```rust
193/// # let a = Some(1);
194/// # let b = Some(2);
195/// let v: i32 = if let Some(va) = a {
196/// if let Some(vb) = b {
197/// { 1 }
198/// } else { { 2 } }
199/// } else { { 2 } };
200/// # assert_eq!(v, 1);
201/// ```
202/// - `!loop bool`
203/// ```rust
204/// # use libsugar::*;
205/// # let a = Some(1);
206/// # let b = Some(2);
207/// let v: bool = bop!(!loop bool match && Some(va) = a, Some(vb) = b => {
208/// 1
209/// } else {
210/// 2
211/// });
212/// # assert!(v);
213/// ```
214/// *equivalent to*
215/// ```rust
216/// # let a = Some(1);
217/// # let b = Some(2);
218/// let v: bool = if let Some(va) = a {
219/// if let Some(vb) = b {
220/// { 1 }; true
221/// } else { { 2 }; false }
222/// } else { { 2 }; false };
223/// # assert!(v);
224/// ```
225/// - **In**
226/// ```rust
227/// # use libsugar::*;
228/// let r = 0..5;
229/// let c = bop!(&1, &2 => in && r);
230/// # assert!(c);
231/// ```
232/// *equivalent to*
233/// ```rust
234/// let r = 0..5;
235/// let c = r.contains(&1) && r.contains(&2);
236/// # assert!(c);
237/// ```
238/// - `||`
239/// ```rust
240/// # use libsugar::*;
241/// # let r = 0..5;
242/// let c = bop!(&1, &2 => in || r);
243/// # assert!(c);
244/// ```
245/// *equivalent to*
246/// ```rust
247/// # let r = 0..5;
248/// let c = r.contains(&1) || r.contains(&2);
249/// # assert!(c);
250/// ```
251/// - custom funcion name
252/// ```ignore
253/// let c = bop!(has; &1, &2 => in && r);
254/// ```
255/// *equivalent to*
256/// ```ignore
257/// let c = r.has(&1) && r.has(&2);
258/// ```
259#[macro_export(local_inner_macros)]
260macro_rules! bop {
261 {} => { };
262
263 // let op
264 { let $($p:pat $(| $t:ty)? $(= $e:expr)?),*} => { $(let $p $(: $t)? $(= $e)?;)* };
265
266 // if let op
267 { $($l:lifetime :)? match && $($p:pat = $e:expr),* => $b:block else $el:block } => {
268 $($l :)? loop { _matchand!( $( $p = $e ; { } )* ; { break $($l)? $b ; }) ; break $($l)? $el; }
269 };
270 { bool $($l:lifetime :)? match && $($p:pat = $e:expr),* => $b:block $(else $el:block)? } => {
271 $($l :)? loop { _matchand!( $( $p = $e ; { } )* ; { $b ; break $($l)? true; }) ; $($el ;)? break $($l)? false; }
272 };
273 { !loop match && $($p:pat = $e:expr),* => $b:block else $el:block } => {
274 _matchand!( $( $p = $e ; { } )* ; { $b } { $el })
275 };
276 { !loop bool match && $($p:pat = $e:expr),* => $b:block $(else $el:block)? } => {
277 _matchand!( $( $p = $e ; { } )* ; { $b ; true } { $($el ;)? false })
278 };
279
280 // base op
281 { $x:expr $(;)? } => { $x };
282 { || $x:expr $(;)? } => { $x };
283 { && $x:expr $(;)? } => { $x };
284 { = $x:ident $(;)? } => { };
285 { || $x:expr ; $($op:tt $a:expr $(;$n:tt)?),* } => { $(_select_op!($x; $op $a $(;$n)?))||* };
286 { && $x:expr ; $($op:tt $a:expr $(;$n:tt)?),* } => { $(_select_op!($x; $op $a $(;$n)?))&&* };
287 { = $x:ident ; $($op:tt $a:expr $(;$n:tt)?),* } => { $($x = _select_op!($x; $op $a $(;$n)?));* ; };
288 // batch op
289 { || $x:expr ; $op:tt $(;)? } => { $x };
290 { && $x:expr ; $op:tt $(;)? } => { $x };
291 { = $x:ident ; $op:tt $(;)? } => { };
292 { || $x:expr ; $op:tt ; $($a:expr $(;$n:tt)?),* } => { $(_select_op!($x; $op $a $(;$n)?))||* };
293 { && $x:expr ; $op:tt ; $($a:expr $(;$n:tt)?),* } => { $(_select_op!($x; $op $a $(;$n)?))||* };
294 { = $x:ident ; $op:tt ; $($a:expr $(;$n:tt)?),* } => { $($x = _select_op!($x; $op $a $(;$n)?));* ; };
295
296 // inop
297 { $fname:ident ; $($v:expr),* => in && $t:expr } => { $($t.$fname($v))&&* };
298 { $fname:ident ; $($v:expr),* => in || $t:expr } => { $($t.$fname($v))||* };
299 { $fname:ident ; $v:expr => in && $($t:expr),* } => { $($t.$fname($v))&&* };
300 { $fname:ident ; $v:expr => in || $($t:expr),* } => { $($t.$fname($v))||* };
301
302 { $($fname:ident ;)? => in && $t:expr } => { false };
303 { $($fname:ident ;)? => in || $t:expr } => { false };
304 { $($fname:ident ;)? $v:expr => in && } => { false };
305 { $($fname:ident ;)? $v:expr => in || } => { false };
306
307 { $($v:expr),* => in && $t:expr } => { $($t.contains($v))&&* };
308 { $($v:expr),* => in || $t:expr } => { $($t.contains($v))||* };
309 { $v:expr => in && $($t:expr),* } => { $($t.contains($v))&&* };
310 { $v:expr => in || $($t:expr),* } => { $($t.contains($v))||* };
311}
312
313#[cfg(feature = "side-effect")]
314pub mod side_effect;
315#[cfg(all(feature = "side-effect", feature = "re-exports"))]
316pub use side_effect::*;
317
318#[cfg(feature = "macro-lit")]
319mod macro_lit;
320#[cfg(feature = "macro-lit")]
321pub use macro_lit::*;
322
323#[cfg(feature = "named-into")]
324pub mod named_into;
325#[cfg(all(feature = "named-into", feature = "re-exports"))]
326pub use named_into::*;
327
328#[cfg(feature = "combin")]
329pub mod combin;
330#[cfg(all(feature = "combin", feature = "re-exports"))]
331pub use combin::*;
332
333#[cfg(all(feature = "chain_panic", feature = "std"))]
334pub mod chain_panic;
335#[cfg(all(feature = "chain_panic", feature = "std", feature = "re-exports"))]
336pub use chain_panic::*;
337
338#[cfg(feature = "chain_todo")]
339pub mod chain_todo;
340#[cfg(all(feature = "chain_todo", feature = "re-exports"))]
341pub use chain_todo::*;
342
343#[cfg(feature = "tuples")]
344/// Re-exports from [tuples](https://crates.io/crates/tuples)
345pub mod tuples {
346 pub use tuples::*;
347}
348#[cfg(all(feature = "tuples", feature = "re-exports"))]
349pub use crate::tuples::*;
350
351#[cfg(feature = "once_get")]
352pub mod once_get;
353#[cfg(all(feature = "once_get", feature = "re-exports"))]
354pub use crate::once_get::*;
355
356#[cfg(feature = "chain_drop")]
357pub mod chain_drop;
358#[cfg(all(feature = "chain_drop", feature = "re-exports"))]
359pub use chain_drop::*;
360
361#[cfg(test)]
362mod tests;