Skip to content

Instantly share code, notes, and snippets.

@KallDrexx
Forked from anonymous/playground.rs
Created August 29, 2016 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KallDrexx/6d5112715a0fc29d46353188078ec725 to your computer and use it in GitHub Desktop.
Save KallDrexx/6d5112715a0fc29d46353188078ec725 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
//#![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