1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use proc_macro2::Span;
use quote::{ToTokens, TokenStreamExt};
use std::collections::HashSet;

/// The index attribute.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Idx {
    /// A regular, non-borrowing index.
    N(u32),
    /// An index which indicates that the value borrows from the decoding input.
    B(u32)
}

impl ToTokens for Idx {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        tokens.append(proc_macro2::Literal::u32_unsuffixed(self.val()))
    }
}

impl Idx {
    /// Test if `Idx` is the `B` variant.
    pub fn is_b(self) -> bool {
        matches!(self, Idx::B(_))
    }

    /// Get the numeric index value.
    pub fn val(self) -> u32 {
        match self {
            Idx::N(i) => i,
            Idx::B(i) => i
        }
    }
}

/// Check that there are no duplicate `Idx` values in `iter`.
pub fn check_uniq<'a, I>(s: Span, iter: I) -> syn::Result<()>
where
    I: IntoIterator<Item = &'a Idx>
{
    let mut set = HashSet::new();
    let mut ctr = 0;
    for u in iter {
        set.insert(u.val());
        ctr += 1;
    }
    if ctr != set.len() {
        return Err(syn::Error::new(s, "duplicate index numbers"))
    }
    Ok(())
}