Skip to content

Instantly share code, notes, and snippets.

@ckampfe
Last active September 21, 2021 01:07
Show Gist options
  • Save ckampfe/b0cbbdec763525f3cbd829459aa3e4ee to your computer and use it in GitHub Desktop.
Save ckampfe/b0cbbdec763525f3cbd829459aa3e4ee to your computer and use it in GitHub Desktop.
access a deeply nested enum/map combo
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
pub enum Bencode<'a> {
String(&'a [u8]),
Integer(isize),
List(Vec<Bencode<'a>>),
Dictionary(BTreeMap<&'a [u8], Bencode<'a>>),
}
#[macro_export]
macro_rules! get_in {
($bencode:expr, $($key:expr),*) => {
{
let mut r = Some(&$bencode);
$(
r = if let Some($crate::Bencode::Dictionary(ref d)) = r {
d.get($key)
} else {
None
};
)*
r
}
};
}
#[test]
fn get_in_macro() {
let nested = Bencode::Dictionary(map![
b"info".as_ref(),
Bencode::Dictionary(map![
b"size".as_ref(),
Bencode::Integer(8),
b"type".as_ref(),
Bencode::String(b"torrent".as_ref()),
b"deeper".as_ref(),
Bencode::Dictionary(map![b"secret".as_ref(), Bencode::Integer(29)])
])
]);
let res = get_in![
nested,
b"info".as_ref(),
b"deeper".as_ref(),
b"secret".as_ref()
];
assert_eq!(res, Some(&Bencode::Integer(29)));
}
// Recursive expansion of get_in! macro
// =====================================
{
let mut r = Some(&nested);
r = if let Some($crate::Bencode::Dictionary(ref d)) = r {
d.get(b"info".as_ref())
}else {
None
};
r = if let Some($crate::Bencode::Dictionary(ref d)) = r {
d.get(b"deeper".as_ref())
}else {
None
};
r = if let Some($crate::Bencode::Dictionary(ref d)) = r {
d.get(b"secret".as_ref())
}else {
None
};
r
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment