Skip to main content

tokel_std/
state.rs

1//! Stateful generation [`Transformer`]s.
2
3use proc_macro2::{Literal, TokenStream};
4use tokel_engine::prelude::{Registry, Transformer};
5
6/// Yields an incrementing integer literal every time it is called.
7///
8/// The integer is internally an [`u32`], and is incremented with wrapping arithmetic.
9#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct Enumerate(u32);
11
12impl Transformer for Enumerate {
13    fn transform(
14        &mut self,
15        _input: TokenStream,
16        _argument: TokenStream,
17    ) -> Result<TokenStream, syn::Error> {
18        let Self(target_count) = self;
19
20        let current_value;
21
22        (current_value, *target_count) = (*target_count, target_count.wrapping_add(1));
23
24        let target_literal = Literal::u32_unsuffixed(current_value);
25
26        Ok(quote::quote!(#target_literal))
27    }
28}
29
30/// Inserts all `state`-related [`Transformer`]s into the specified [`Registry`].
31///
32/// # Errors
33///
34/// This will fail if at least one standard `state`-related [`Transformer`] is already present by-name in the [`Registry`].
35///
36/// On failure, there is no guarantee that other non-colliding transformers have not been registered.
37#[inline]
38pub fn register(registry: &mut Registry) -> Result<(), Box<dyn Transformer>> {
39    registry
40        .try_insert("enumerate", Enumerate::default())
41        .map_err(Box::new)
42        .map_err(|target_value| target_value as Box<dyn Transformer>)?;
43
44    Ok(())
45}