datalit-macros-internals 0.1.0-alpha.4

Internals for the datalit crate
Documentation
use syn::token::Bracket;

use crate::{
    entry::{BlockEntry, literal::LiteralEntry},
    state::StateOperation,
};

#[derive(derive_syn_parse::Parse)]
enum Contents {
    #[peek_with(BlockEntry::peek, name = "sequence of entries")]
    Braced(super::BlockEntry),
    #[peek_with(LiteralEntry::peek, name = "single literal")]
    SingleLiteral(LiteralEntry),
}

impl StateOperation for Contents {
    fn apply_to(&self, state: &mut crate::state::EntryState) -> syn::Result<()> {
        match self {
            Contents::Braced(seq) => seq.apply_to(state),
            Contents::SingleLiteral(lit) => lit.apply_to(state),
        }
    }
}

#[derive(derive_syn_parse::Parse)]
pub struct RepeatEntry {
    #[bracket]
    _brackets: Bracket,
    #[inside(_brackets)]
    contents: Contents,
    #[prefix(syn::Token![;] in _brackets)]
    #[inside(_brackets)]
    count: syn::LitInt,
}

impl RepeatEntry {
    pub fn peek(input: syn::parse::ParseStream) -> bool {
        input.peek(Bracket)
    }
}

impl StateOperation for RepeatEntry {
    fn apply_to(&self, state: &mut crate::state::EntryState) -> syn::Result<()> {
        if !self.count.suffix().is_empty() {
            return Err(syn::Error::new_spanned(
                &self.count,
                "suffixes are not allowed in repeat counts",
            ));
        }
        let count: usize = self.count.base10_parse()?;
        state.freeze_label_context();
        for _ in 0..count {
            self.contents.apply_to(state)?;
        }
        state.unfreeze_label_context();
        Ok(())
    }
}