macroscope 0.1.1

Macroscope makes writing proc macros a breeze
Documentation
use quote::{quote, ToTokens};
use syn::parse::Parse;

use crate::validate::Validate;

#[derive(Debug)]
pub enum Optional<T>
where
    T: Parse + Validate,
{
    Present(T),
    Missing,
}

impl<T> ToTokens for Optional<T>
where
    T: Parse + ToTokens + Validate,
{
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        match self {
            Optional::Present(present) => tokens.extend(quote!(#present)),
            Optional::Missing => {}
        }
    }
}

impl<T> Parse for Optional<T>
where
    T: Parse + Validate,
{
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let is_valid = T::validate(&input);

        if is_valid {
            Ok(Optional::Present(T::parse(&input)?))
        } else {
            Ok(Optional::Missing)
        }
    }
}

#[derive(Debug)]
pub enum OptionalEnd<T>
where
    T: Parse,
{
    Present(T),
    Missing,
}

impl<T> ToTokens for OptionalEnd<T>
where
    T: Parse + ToTokens,
{
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        match self {
            OptionalEnd::Present(present) => tokens.extend(quote!(#present)),
            OptionalEnd::Missing => {}
        }
    }
}

impl<T> Parse for OptionalEnd<T>
where
    T: Parse,
{
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        if input.is_empty() {
            Ok(OptionalEnd::Missing)
        } else {
            let parsed = T::parse(input)?;
            Ok(OptionalEnd::Present(parsed))
        }
    }
}