etest-impl 0.3.0

Implementation of etest's proc_macro part
Documentation
use proc_macro::{Delimiter, Group, TokenStream, TokenTree};

use crate::Error;
use super::ListIterator;

#[derive(Default)]
pub struct TokenSet(Vec<TokenStream>);

impl TokenSet {
    fn from_group(g: Group) -> Result<Self, Error> {
        let mut res = Vec::new();

        for v in ListIterator::new(g.stream()) {
            let v = v.map_err(|_| Error::BadValue)?;

            res.push(v);
        }

        Ok(Self(res))
    }

    pub(super) fn from_stream(tokens: TokenStream) -> Result<Self, Error> {
        let mut iter = tokens.into_iter();

        let res = match iter.next() {
            None					=> return Err(Error::NoValue),
            Some(l @ TokenTree::Literal(_))		=> Self(vec![l.into()]),

            Some(TokenTree::Group(g))
                if matches!(g.delimiter(), Delimiter::Brace | Delimiter::Bracket)
                => Self::from_group(g)?,

            _		=> return Err(Error::BadValue),
        };

        if iter.next().is_some() {
            return Err(Error::ExtraData);
        }

        Ok(res)
    }

    pub fn push(&mut self, tokens: TokenStream) {
        self.0.push(tokens);
    }
}

impl std::ops::Deref for TokenSet {
    type Target = Vec<TokenStream>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl std::fmt::Debug for TokenSet {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut l = f.debug_list();

        for t in &self.0 {
            l.entry(&format!("{}", t));
        }

        l.finish()
    }
}