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;