hax_lib_macros/
hax_paths.rs1use syn::spanned::Spanned;
5use syn::*;
6
7fn expect_simple_path(path: &Path) -> Option<Vec<String>> {
8 let mut chunks = vec![];
9 if path.leading_colon.is_some() {
10 chunks.push(String::new())
11 }
12 for segment in &path.segments {
13 chunks.push(format!("{}", segment.ident));
14 if !matches!(segment.arguments, PathArguments::None) {
15 return None;
16 }
17 }
18 Some(chunks)
19}
20
21pub const DECORATION_KINDS: &[&str] = &["decreases", "ensures", "requires"];
23
24pub fn expects_path_decoration(path: &Path) -> Result<Option<String>> {
28 expects_hax_path(DECORATION_KINDS, path)
29}
30
31pub fn expects_refine(path: &Path) -> Result<Option<String>> {
33 expects_hax_path(&["refine"], path)
34}
35
36pub fn expects_order(path: &Path) -> Result<Option<String>> {
38 expects_hax_path(&["order"], path)
39}
40
41pub fn expects_hax_path(allowlist: &[&str], path: &Path) -> Result<Option<String>> {
44 let path_span = path.span();
45 let path = expect_simple_path(path)
46 .ok_or_else(|| Error::new(path_span, "Expected a simple path, with no `<...>`."))?;
47 Ok(
48 match path
49 .iter()
50 .map(|x| x.as_str())
51 .collect::<Vec<_>>()
52 .as_slice()
53 {
54 [kw] | ["", "hax_lib", kw] | ["hax_lib", kw] if allowlist.contains(kw) => {
55 Some(kw.to_string())
56 }
57 _ => None,
58 },
59 )
60}