algosul_core/codegen/
tokens.rs1use 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}