templr_parser 0.2.1

Parser for templr templates
Documentation
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
use syn::{
    braced,
    parse::{Parse, ParseStream},
    token::{self, Brace},
    Token,
};

use crate::parse_to_vec;

#[derive(Debug, Clone)]
pub struct Arm<T> {
    pub pat: Box<syn::Pat>,
    pub guard: Option<(token::If, Box<syn::Expr>)>,
    pub fat_arrow: token::FatArrow,
    pub brace: Brace,
    pub body: Vec<T>,
}

impl<T: Parse> Parse for Arm<T> {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let content;
        Ok(Self {
            pat: Box::new(syn::Pat::parse_multi_with_leading_vert(input)?),
            guard: match Option::<Token![if]>::parse(input)? {
                Some(tk) => Some((tk, input.parse()?)),
                None => None,
            },
            fat_arrow: input.parse()?,
            brace: braced!(content in input),
            body: parse_to_vec(&content)?,
        })
    }
}

impl<T: ToTokens> ToTokens for Arm<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.pat.to_tokens(tokens);
        if let Some((if_token, expr)) = &self.guard {
            if_token.to_tokens(tokens);
            expr.to_tokens(tokens);
        }
        self.fat_arrow.to_tokens(tokens);
        self.brace.surround(tokens, |tokens| {
            tokens.append_all(&self.body);
        });
    }
}

#[derive(Debug, Clone)]
pub struct Match<T> {
    pub pound: token::Pound,
    pub match_token: token::Match,
    pub expr: Box<syn::Expr>,
    pub brace: Brace,
    pub arms: Vec<Arm<T>>,
}

impl<T: Parse> Parse for Match<T> {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let content;
        Ok(Self {
            pound: input.parse()?,
            match_token: input.parse()?,
            expr: Box::new(syn::Expr::parse_without_eager_brace(input)?),
            brace: braced!(content in input),
            arms: parse_to_vec(&content)?,
        })
    }
}

impl<T: ToTokens> ToTokens for Match<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.pound.to_tokens(tokens);
        self.match_token.to_tokens(tokens);
        self.expr.to_tokens(tokens);
        self.brace.surround(tokens, |tokens| {
            tokens.append_all(&self.arms);
        });
    }
}