tokel_std/state.rs
1//! Stateful generation [`Transformer`]s.
2//!
3//! # Available Transformers
4//!!
5//! | Transformer | Argument Type | Description |
6//! |---------------|-------------------------------|-------------|
7//! | [`Enumerate`] | [`syn::parse::Nothing`] | Yields an incrementing integer literal on each invocation (stateful). |
8//!
9//! # Argument Types
10//!
11//! - [`syn::parse::Nothing`]: No argument required.
12//!
13//! # Examples
14//!
15//! * `[< >]:enumerate` ->`0`
16//! * Calling the same transformer again advances its state: `[< >]:enumerate` ->`1`
17//! * Use `enumerate` inside another transformer's argument:
18//! * `[< b c >]:push_left[[[< >]:enumerate]]` ->`0 b c`
19//! * `[< b c >]:push_right[[[< >]:enumerate]]` ->`b c 1`
20
21use proc_macro2::{Literal, TokenStream};
22
23use quote::ToTokens;
24use tokel_engine::prelude::{Pass, Registry, Transformer};
25
26/// Yields an incrementing integer literal every time it is called.
27///
28/// # Argument
29///
30/// This takes no argument.
31///
32/// # Examples
33///
34/// * `[< >]:enumerate` ->`0`
35/// * As an argument to another transformer: `[< a b >]:push_left[[[< >]:enumerate]]` ->`0 a b`
36///
37/// # Remarks
38///
39/// The integer is internally an [`u32`], and is incremented with wrapping arithmetic.
40#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub struct Enumerate(u32);
42
43impl Pass for Enumerate {
44 type Argument = syn::parse::Nothing;
45
46 fn through(&mut self, _: TokenStream, _: Self::Argument) -> syn::Result<TokenStream> {
47 let Self(enumerate_counter) = self;
48
49 let current_value;
50 (current_value, *enumerate_counter) =
51 (*enumerate_counter, enumerate_counter.wrapping_add(1));
52
53 Ok(Literal::u32_unsuffixed(current_value).into_token_stream())
54 }
55}
56
57/// Inserts all `state`-related [`Transformer`]s into the specified [`Registry`].
58///
59/// # Errors
60///
61/// This will fail if at least one standard `state`-related [`Transformer`] is already present by-name in the [`Registry`].
62///
63/// On failure, there is no guarantee that other non-colliding transformers have not been registered.
64#[inline]
65pub fn register(registry: &mut Registry) -> Result<(), Box<dyn Transformer>> {
66 registry
67 .try_insert("enumerate", Enumerate::default())
68 .map_err(Box::new)
69 .map_err(|target_value| target_value as Box<dyn Transformer>)?;
70
71 Ok(())
72}