easy_switch/lib.rs
1#![no_std]
2
3//! A traditional C-style switch expression. In contrast to traditional `match` expressions, the
4//! [switch!](switch) macro will test against expressions, not patterns. The API of this crate is
5//! tiny, with just a single item.
6//!
7//! Internally, `switch!` just expands to a bunch of if-else expressions!
8//!
9//! # Example
10//!
11//! ```
12//! use easy_switch::switch;
13//!
14//! let num = 50;
15//! let case1 = 20;
16//! let case2 = 30;
17//! let matching = switch! { num;
18//! case1 => "case1",
19//! case2 => "case2",
20//! 25 + 25 => "unnamed case",
21//! _ => "default case",
22//! };
23//! assert_eq!("unnamed case", matching);
24//! ```
25//!
26//! # Multiple Conditions
27//!
28//! Multiple conditions can be chained together with a comma.
29//! ```
30//! use easy_switch::switch;
31//!
32//! #[derive(PartialEq, Eq)]
33//! struct Example {
34//! field: i32,
35//! field2: i32,
36//! }
37//!
38//! impl Example {
39//! pub fn new(field2: i32) -> Self {
40//! Self {
41//! field: 10,
42//! field2,
43//! }
44//! }
45//! }
46//!
47//! let switchable = Example::new(10);
48//! let result = switch! { switchable;
49//! Example::new(50), 50 == 50 => 50,
50//! Example::new(20), 50 == 50, 20 == 20 => 20,
51//! _ => 0,
52//! };
53//! assert_eq!(0, result);
54//! ```
55
56/// The macro used to emulate switch statements.
57///
58/// See the [crate level docs](../easy_switch/index.html) for more.
59///
60/// # Example
61///
62/// ```
63/// use easy_switch::switch;
64///
65/// let var = 30;
66/// let matched = switch! { var;
67/// 15 + 15 => true,
68/// 22 => {
69/// println!("22?");
70/// false
71/// },
72/// _ => false,
73/// };
74/// assert!(matched);
75#[macro_export]
76macro_rules! switch {
77 // Single case
78 ($input:expr; $first:expr$(, $($conditions:expr),*)? => $execute:expr$(,)?) => {
79 if $input == $first $(&& $($conditions)&&*)? { $execute }
80 };
81
82 // Single case with else
83 ($input:expr; $first:expr$(, $($conditions:expr),*)? => $execute:expr, _ => $execute_last:expr$(,)?) => {
84 if $input == $first $(&& $($conditions)&&*)? { $execute }
85 else { $execute_last }
86 };
87
88 // Multi-case
89 ($input:expr; $first:expr$(, $($conditions:expr),*)? => $execute:expr, $($rest:expr$(, $($conditions_rest:expr),*)? => $exec:expr),+$(,)?) => {
90 if $input == $first $(&& $($conditions)&&*)? { $execute }
91 $(else if $input == $rest $(&& $($conditions_rest)&&*)? { $exec })*
92 };
93
94 // Multi-case with else
95 ($input:expr; $first:expr$(, $($conditions:expr),*)? => $execute:expr, $($rest:expr$(, $($conditions_rest:expr),*)? => $exec:expr),+, _ => $execute_last:expr$(,)?) => {
96 if $input == $first $(&& $($conditions)&&*)? { $execute }
97 $(else if $input == $rest $(&& $($conditions_rest)&&*)? { $exec })*
98 else { $execute_last }
99 };
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn single_case() {
108 let x = 3;
109 switch! { x;
110 3 => (),
111 }
112 }
113
114 #[test]
115 fn single_case_with_else() {
116 let x = 3;
117 switch! { x;
118 3 => (),
119 _ => (),
120 }
121 }
122
123 #[test]
124 fn multi_case() {
125 let x = 3;
126 switch! { x;
127 3 => (),
128 3 => (),
129 3 => (),
130 3 => (),
131 }
132 }
133
134 #[test]
135 fn multi_case_with_else() {
136 let x = 3;
137 switch! { x;
138 3 => (),
139 3 => (),
140 3 => (),
141 3 => (),
142 _ => (),
143 }
144 }
145}