-
-
Save KallDrexx/6d5112715a0fc29d46353188078ec725 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#![feature(trace_macros)] | |
//trace_macros!(true); | |
macro_rules! assert_vec_match{ | |
(@empty $vector:expr) => { | |
if $vector.len() > 0 { | |
panic!("Expected an empty vector, but the vector contained {} elements", $vector.len()); | |
} | |
}; | |
(@match $idx:expr, $vector:expr, $pattern:pat if $cond:expr => $success:expr) => { | |
if $vector.len() <= $idx { | |
panic!("Could not match on index {} as the vector only has {} values", $idx, $vector.len()); | |
} | |
match $vector[$idx] { | |
$pattern if $cond => $success, | |
_ => panic!("Match failed on index {}: {:?} vs {} ", $idx, $vector[$idx], stringify!($pattern)) | |
}; | |
}; | |
(@step $idx:expr, $vector:expr,) => { | |
if $vector.len() > $idx { | |
panic!("Vector contained {} elements but only {} was expected!", $vector.len(), $idx); | |
} | |
}; | |
(@step $idx:expr, $vector:expr) => { | |
if $vector.len() > $idx { | |
panic!("Vector contained {} elements but only {} was expected!", $vector.len(), $idx); | |
} | |
}; | |
// pattern if condition | |
(@step $idx:expr, $vector:expr, $pattern:pat if $cond:expr, $($rest:tt)*) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if $cond => ()); | |
assert_vec_match!(@step $idx + 1usize, $vector, $($rest)*); | |
}; | |
(@step $idx:expr, $vector:expr, $pattern:pat if $cond:expr) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if $cond => $success); | |
}; | |
// pattern if condition => success | |
(@step $idx:expr, $vector:expr, $pattern:pat if $cond:expr => $success:expr, $($rest:tt)*) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if $cond => $success); | |
assert_vec_match!(@step $idx + 1usize, $vector, $($rest)*); | |
}; | |
(@step $idx:expr, $vector:expr, $pattern:pat if $cond:expr => $success:expr) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if $cond => $success); | |
}; | |
// pattern => success | |
(@step $idx:expr, $vector:expr, $pattern:pat => $success:expr, $($rest:tt)*) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if true => $success); | |
assert_vec_match!(@step $idx + 1usize, $vector, $($rest)*); | |
}; | |
(@step $idx:expr, $vector:expr, $pattern:pat => $success:expr) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if true => $success); | |
}; | |
// pattern only | |
(@step $idx:expr, $vector:expr, $pattern:pat, $($rest:tt)*) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if true => ()); | |
assert_vec_match!(@step $idx + 1usize, $vector, $($rest)*); | |
}; | |
(@step $idx:expr, $vector:expr, $pattern:pat) => { | |
assert_vec_match!(@match $idx, $vector, $pattern if true => ()); | |
}; | |
// Entrypoints | |
($vector:expr, $pattern:pat if $cond:expr, $($rest:tt)*) => { | |
assert_vec_match!(@step 0usize, $vector, $pattern if $cond => (), $($rest)*); | |
}; | |
($vector:expr, $pattern:pat => $success:expr, $($rest:tt)*) => { | |
assert_vec_match!(@step 0usize, $vector, $pattern if true => $success, $($rest)*); | |
}; | |
($vector:expr, $pattern:pat if $cond:expr => $success:expr, $($rest:tt)*) => { | |
assert_vec_match!(@step 0usize, $vector, $pattern if $cond => $success, $($rest)*); | |
}; | |
($vector:expr, $pattern:pat, $($rest:tt)*) => { | |
assert_vec_match!(@step 0usize, $vector, $pattern if true => (), $($rest)*); | |
}; | |
// Empty macro after vector | |
($vector:expr) => { | |
assert_vec_match!(@empty $vector); | |
}; | |
($vector:expr,) => { | |
assert_vec_match!(@empty $vector); | |
}; | |
} | |
fn main() { | |
let test1 = Test::Value1 { v1: 5, v2: "test".to_string() }; | |
let test2 = Test::Value1 { v1: 8, v2: "test2".to_string() }; | |
let test3 = Test::Value1 { v1: 8, v2: "test3".to_string() }; | |
let test4 = Test::Value1 { v1: 8, v2: "test4".to_string() }; | |
let vector = vec![test2, test1, test3, test4]; | |
let result; | |
assert_vec_match!(vector, | |
Test::Value1 { v1: _, ref v2} if v2 == "test2", | |
Test::Value1 { v1, ref v2} if v2 == "test" => {result = v1}, | |
Test::Value1 { v1: 8, v2: _} => (), | |
Test::Value1 { v1: 8, v2: _}, | |
); | |
//assert_vec_match!(vector); | |
println!("{}", result); | |
} | |
#[derive(Debug)] | |
enum Test { | |
Value1 { v1: u32, v2: String } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment