1use crate::value::{Value, ValueExpr, ValueIterExpr, Verbatim};
2use proc_macro2::TokenStream;
3use quote::ToTokens;
4use std::marker::PhantomData;
5use syn::parse::{self, Parse, ParseStream};
6use syn::punctuated::{Pair, Punctuated};
7use syn::Token;
8
9pub struct SeqInput<V = Verbatim> {
11 values: Punctuated<Value<V>, Token![,]>,
12 _phantom: PhantomData<V>,
13}
14
15impl<V> Parse for SeqInput<V>
16where
17 Value<V>: Parse,
18{
19 fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
20 Ok(SeqInput {
21 values: input.parse_terminated(Value::parse)?,
22 _phantom: PhantomData,
23 })
24 }
25}
26
27impl<V> SeqInput<V>
28where
29 ValueExpr<V>: ToTokens,
30 ValueIterExpr<V>: ToTokens,
31{
32 pub fn is_simple(&self) -> bool {
34 self.values.iter().all(Value::is_simple)
35 }
36
37 pub fn values(&self) -> impl ExactSizeIterator<Item = &Value<V>> {
38 self.values.iter()
39 }
40
41 pub fn simple_output(self) -> TokenStream {
42 self.values
43 .into_pairs()
44 .map(Pair::into_tuple)
45 .map(|(value, delim)| Pair::new(value.into_token_stream(), delim).into_token_stream())
46 .collect()
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use std::str::FromStr as _;
54 use syn::Expr;
55
56 #[test]
57 fn parse_empty_input_as_empty_sequence() {
58 let tokens = TokenStream::from_str("").unwrap();
59 let seq: SeqInput<Verbatim> = syn::parse2(tokens).unwrap();
60 assert!(seq.values().next().is_none());
61 }
62
63 #[test]
64 fn parse_single_expression_as_one_value_of_one() {
65 let tokens = TokenStream::from_str("a + b").unwrap();
66 let seq: SeqInput<Verbatim> = syn::parse2(tokens.clone()).unwrap();
67 let expected_expr: Expr = syn::parse2(tokens).unwrap();
68 let values: Vec<_> = seq.values().collect();
69 assert_eq!(values.len(), 1);
70 assert!(matches!(values[0], Value::One(ValueExpr { expr, .. }) if *expr == expected_expr));
71 }
72
73 #[test]
74 fn parse_single_spread_expression_as_one_value_of_many() {
75 let source = "..a + b";
76 let tokens = TokenStream::from_str(source).unwrap();
77 let seq: SeqInput<Verbatim> = syn::parse2(tokens).unwrap();
78 let expected_expr: Expr = {
79 let tokens = TokenStream::from_str(source.strip_prefix("..").unwrap()).unwrap();
80 syn::parse2(tokens).unwrap()
81 };
82 let values: Vec<_> = seq.values().collect();
83 assert_eq!(values.len(), 1);
84 assert!(
85 matches!(values[0], Value::Many(ValueIterExpr { expr, .. }) if *expr == expected_expr)
86 );
87 }
88
89 #[test]
90 fn empty_input_is_simple() {
91 let tokens = TokenStream::from_str("").unwrap();
92 let seq: SeqInput<Verbatim> = syn::parse2(tokens).unwrap();
93 assert!(seq.is_simple());
94 }
95
96 #[test]
97 fn non_spread_input_is_simple() {
98 let tokens = TokenStream::from_str("a, b, c").unwrap();
99 let seq: SeqInput<Verbatim> = syn::parse2(tokens).unwrap();
100 assert!(seq.is_simple());
101 }
102
103 #[test]
104 fn spread_input_is_not_simple() {
105 let tokens = TokenStream::from_str("a, ..b, c").unwrap();
106 let seq: SeqInput<Verbatim> = syn::parse2(tokens).unwrap();
107 assert!(!seq.is_simple());
108 }
109}