hax_lib_macros/
hax_paths.rsuse syn::spanned::Spanned;
use syn::*;
fn expect_simple_path(path: &Path) -> Option<Vec<String>> {
let mut chunks = vec![];
if path.leading_colon.is_some() {
chunks.push(String::new())
}
for segment in &path.segments {
chunks.push(format!("{}", segment.ident));
if !matches!(segment.arguments, PathArguments::None) {
return None;
}
}
Some(chunks)
}
pub const DECORATION_KINDS: &[&str] = &["decreases", "ensures", "requires"];
pub fn expects_path_decoration(path: &Path) -> Result<Option<String>> {
expects_hax_path(DECORATION_KINDS, path)
}
pub fn expects_refine(path: &Path) -> Result<Option<String>> {
expects_hax_path(&["refine"], path)
}
pub fn expects_hax_path(allowlist: &[&str], path: &Path) -> Result<Option<String>> {
let path_span = path.span();
let path = expect_simple_path(path)
.ok_or_else(|| Error::new(path_span, "Expected a simple path, with no `<...>`."))?;
Ok(
match path
.iter()
.map(|x| x.as_str())
.collect::<Vec<_>>()
.as_slice()
{
[kw] | ["", "hax_lib", kw] | ["hax_lib", kw] if allowlist.contains(kw) => {
Some(kw.to_string())
}
_ => None,
},
)
}