fluid_attributes 0.4.0

Proc macro attributes for the fluid crate.
Documentation
use pm::{Span, TokenStream, TokenTree};
use quote::quote;
use syn::{parse::Error, parse_quote};

/// See the method documentation.
pub trait CaseArgs {
    /// Returns the arguments of a `case` as a TokenStream.
    fn stream_args(self) -> Result<TokenStream, Error>;
}

impl CaseArgs for TokenStream {
    fn stream_args(self) -> Result<TokenStream, Error> {
        let mut it = self.into_iter();
        match it.next() {
            Some(args) => {
                let span = args.span();
                match args {
                    TokenTree::Group(group) => Ok(group.stream()),
                    _ => Err(Error::new(
                        span,
                        "A case must have the list of the arguments.",
                    )),
                }
            }
            None => Err(Error::new(Span::call_site(), "A case must have arguments.")),
        }
    }
}

pub trait StringJoiner {
    fn join(self) -> String;
}

impl<T> StringJoiner for T
where
    T: Iterator<Item = String> + Sized,
{
    fn join(mut self) -> String {
        let first = self.next().unwrap_or_default();

        self.fold(first, |acc, s| acc + ", " + &s)
    }
}

/// Zips 3 iterator into an iterator that yields 3-tuples.
pub fn zip2<I1, I2, I3>(
    it1: I1,
    it2: I2,
    it3: I3,
) -> impl Iterator<Item = (I1::Item, I2::Item, I3::Item)>
where
    I1: IntoIterator,
    I2: IntoIterator,
    I3: IntoIterator,
{
    it1.into_iter()
        .zip(it2.into_iter())
        .zip(it3.into_iter())
        .map(|((i, j), k)| (i, j, k))
}

/// Add the `#[test]` attribute to the vector of attributes.
pub fn add_test_attribute(attrs: &mut Vec<syn::Attribute>) {
    attrs.push(parse_quote!(#[test]))
}