algosul_core/codegen/
tokens.rs

1use proc_macro2::{Span, TokenStream};
2use quote::{quote_spanned, ToTokens};
3use syn::{
4    braced,
5    bracketed,
6    parse::{Parse, ParseBuffer, ParseStream},
7    punctuated::Punctuated,
8    token,
9};
10#[derive(Clone)]
11pub struct ArrayBase<B, T: Parse, S: Parse> {
12    #[allow(dead_code)]
13    pub token: B,
14    pub elems: Punctuated<T, S>,
15}
16pub type Array<T> = ArrayBase<token::Bracket, T, token::Comma>;
17pub type Block<T> = ArrayBase<token::Brace, T, token::Semi>;
18impl<B: ToTokens, T: Parse + ToTokens, S: Parse + ToTokens>
19    From<ArrayBase<B, T, S>> for TokenStream
20{
21    fn from(val: ArrayBase<B, T, S>) -> Self { val.into_token_stream() }
22}
23impl<B: ToTokens, T: Parse + ToTokens, S: Parse + ToTokens>
24    From<ArrayBase<B, T, S>> for Vec<T>
25{
26    fn from(val: ArrayBase<B, T, S>) -> Self { val.into_elems().collect() }
27}
28impl<B, T: Parse, S: Parse> ArrayBase<B, T, S> {
29    pub fn elems(&self) -> impl Iterator<Item = &T> { self.elems.iter() }
30
31    pub fn into_elems(self) -> impl Iterator<Item = T> {
32        self.elems.into_iter()
33    }
34
35    pub fn to_token_stream(&self) -> TokenStream
36    where
37        B: ToTokens,
38        T: ToTokens,
39        S: ToTokens,
40    {
41        let token = &self.token;
42        let elems = &self.elems;
43        quote_spanned! {Span::call_site()=>
44            #token #elems #token
45        }
46    }
47
48    pub fn into_token_stream(self) -> TokenStream
49    where
50        B: ToTokens,
51        T: ToTokens,
52        S: ToTokens,
53    {
54        let token = self.token;
55        let elems = self.elems;
56        quote_spanned! {Span::call_site()=>
57            #token #elems #token
58        }
59    }
60
61    fn parse_from_context(content: ParseBuffer, token: B) -> syn::Result<Self> {
62        let mut elems = Punctuated::new();
63        while !content.is_empty() {
64            let first: T = content.parse()?;
65            elems.push_value(first);
66            if content.is_empty() {
67                break;
68            }
69            let punct = content.parse()?;
70            elems.push_punct(punct);
71        }
72        Ok(Self { token, elems })
73    }
74}
75impl<T: Parse> Parse for Array<T> {
76    fn parse(input: ParseStream) -> syn::Result<Self> {
77        let content;
78        let token = bracketed!(content in input);
79        Self::parse_from_context(content, token)
80    }
81}
82impl<T: Parse> Parse for Block<T> {
83    fn parse(input: ParseStream) -> syn::Result<Self> {
84        let content;
85        let token = braced!(content in input);
86        Self::parse_from_context(content, token)
87    }
88}