statue 0.3.1

Easier way to query selectors for static HTML pages.
Documentation
use core::marker::PhantomData;
use proc_macro::{token_stream::IntoIter as TokenTreeIter, TokenTree};

use crate::util::ResultLike;

use super::Parse;

pub(crate) enum Error<T: Parse> {
    SomeOrNoneExpected,
    ParenGroupExpected,
    InnerError(T::Error),
}

pub(crate) struct OptionCombinator<T>(PhantomData<*const T>);

impl<T: Parse> Parse for OptionCombinator<T>
where
    T::Wrapper<T::OkTy, T::Error>: ResultLike<T::OkTy, T::Error>,
{
    type Error = Error<T>;
    type OkTy = Option<T::OkTy>;
    type Wrapper<O, E> = Result<O, E>;

    fn parse(iter: &mut TokenTreeIter) -> Self::Wrapper<Self::OkTy, Self::Error> {
        let Some(ident) = iter.next() else { return Err(Error::SomeOrNoneExpected) };
        let TokenTree::Ident(ident) = ident else { return Err(Error::SomeOrNoneExpected) };
        match ident.to_string().as_str() {
            "None" => Ok(None),
            "Some" => {
                let Some(paren_group) = iter.next() else { return Err(Error::ParenGroupExpected) };
                let TokenTree::Group(paren_group) = paren_group else { return Err(Error::ParenGroupExpected) };
                if paren_group.delimiter() != proc_macro::Delimiter::Parenthesis {
                    return Err(Error::ParenGroupExpected);
                };
                let mut paren_group_contents_iter = paren_group.stream().into_iter();
                T::parse(&mut paren_group_contents_iter)
                    .map(Some)
                    .map_err(Error::InnerError)
            }
            _ => Err(Error::SomeOrNoneExpected),
        }
    }
}