syn_solidity/variable/
list.rs1use crate::{SolIdent, Spanned, Type, VariableDeclaration};
2use proc_macro2::Span;
3use std::{
4 fmt,
5 ops::{Deref, DerefMut},
6};
7use syn::{
8 parse::{Parse, ParseStream},
9 punctuated::Punctuated,
10 Result, Token,
11};
12
13pub type ParameterList = Parameters<syn::token::Comma>;
18
19pub type FieldList = Parameters<syn::token::Semi>;
21
22#[derive(Clone, Default, PartialEq, Eq)]
28pub struct Parameters<P>(Punctuated<VariableDeclaration, P>);
29
30impl Default for &ParameterList {
31 #[inline]
32 fn default() -> Self {
33 const NEW: &ParameterList = &ParameterList::new();
34 NEW
35 }
36}
37
38impl Default for &FieldList {
39 #[inline]
40 fn default() -> Self {
41 const NEW: &FieldList = &FieldList::new();
42 NEW
43 }
44}
45
46impl<P> Deref for Parameters<P> {
47 type Target = Punctuated<VariableDeclaration, P>;
48
49 fn deref(&self) -> &Self::Target {
50 &self.0
51 }
52}
53
54impl<P> DerefMut for Parameters<P> {
55 fn deref_mut(&mut self) -> &mut Self::Target {
56 &mut self.0
57 }
58}
59
60impl fmt::Display for ParameterList {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 for (i, param) in self.iter().enumerate() {
63 if i > 0 {
64 f.write_str(", ")?;
65 }
66 param.fmt(f)?;
67 }
68 Ok(())
69 }
70}
71
72impl fmt::Display for FieldList {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 for (i, field) in self.iter().enumerate() {
75 if i > 0 {
76 f.write_str(" ")?;
77 }
78 field.fmt(f)?;
79 f.write_str(";")?;
80 }
81 Ok(())
82 }
83}
84
85impl<P> fmt::Debug for Parameters<P> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 f.debug_list().entries(self.iter()).finish()
88 }
89}
90
91impl Parse for ParameterList {
93 fn parse(input: ParseStream<'_>) -> Result<Self> {
94 input.parse_terminated(VariableDeclaration::parse, Token![,]).map(Self)
95 }
96}
97
98impl Parse for FieldList {
100 fn parse(input: ParseStream<'_>) -> Result<Self> {
101 let this = input.parse_terminated(VariableDeclaration::parse_with_name, Token![;])?;
102 if this.is_empty() {
103 Err(input.error("defining empty structs is disallowed"))
104 } else if !this.trailing_punct() {
105 Err(input.error("expected trailing semicolon"))
106 } else {
107 Ok(Self(this))
108 }
109 }
110}
111
112impl<P: Spanned> Spanned for Parameters<P> {
113 fn span(&self) -> Span {
114 self.0.span()
115 }
116
117 fn set_span(&mut self, span: Span) {
118 self.0.set_span(span);
119 }
120}
121
122impl<P> IntoIterator for Parameters<P> {
123 type IntoIter = <Punctuated<VariableDeclaration, P> as IntoIterator>::IntoIter;
124 type Item = <Self::IntoIter as Iterator>::Item;
125
126 fn into_iter(self) -> Self::IntoIter {
127 self.0.into_iter()
128 }
129}
130
131impl<'a, P> IntoIterator for &'a Parameters<P> {
132 type IntoIter = syn::punctuated::Iter<'a, VariableDeclaration>;
133 type Item = <Self::IntoIter as Iterator>::Item;
134
135 fn into_iter(self) -> Self::IntoIter {
136 self.0.iter()
137 }
138}
139
140impl<'a, P> IntoIterator for &'a mut Parameters<P> {
141 type IntoIter = syn::punctuated::IterMut<'a, VariableDeclaration>;
142 type Item = <Self::IntoIter as Iterator>::Item;
143
144 fn into_iter(self) -> Self::IntoIter {
145 self.0.iter_mut()
146 }
147}
148
149impl<P: Default> FromIterator<VariableDeclaration> for Parameters<P> {
150 fn from_iter<T: IntoIterator<Item = VariableDeclaration>>(iter: T) -> Self {
151 Self(Punctuated::from_iter(iter))
152 }
153}
154
155impl<P> Parameters<P> {
156 pub const fn new() -> Self {
157 Self(Punctuated::new())
158 }
159
160 pub fn eip712_signature(&self, mut name: String) -> String {
161 name.reserve(2 + self.len() * 32);
162 name.push('(');
163 for (i, field) in self.iter().enumerate() {
164 if i > 0 {
165 name.push(',');
166 }
167 field.fmt_eip712(&mut name).unwrap();
168 }
169 name.push(')');
170 name
171 }
172
173 pub fn names(
174 &self,
175 ) -> impl ExactSizeIterator<Item = Option<&SolIdent>> + DoubleEndedIterator + Clone {
176 self.iter().map(|var| var.name.as_ref())
177 }
178
179 pub fn types(&self) -> impl ExactSizeIterator<Item = &Type> + DoubleEndedIterator + Clone {
180 self.iter().map(|var| &var.ty)
181 }
182
183 pub fn types_mut(&mut self) -> impl ExactSizeIterator<Item = &mut Type> + DoubleEndedIterator {
184 self.iter_mut().map(|var| &mut var.ty)
185 }
186
187 pub fn types_and_names(
188 &self,
189 ) -> impl ExactSizeIterator<Item = (&Type, Option<&SolIdent>)> + DoubleEndedIterator {
190 self.iter().map(|p| (&p.ty, p.name.as_ref()))
191 }
192
193 pub fn type_strings(
194 &self,
195 ) -> impl ExactSizeIterator<Item = String> + DoubleEndedIterator + Clone + '_ {
196 self.iter().map(|var| var.ty.to_string())
197 }
198
199 #[cfg(feature = "visit")]
200 pub fn visit_types(&self, mut f: impl FnMut(&Type)) {
201 for ty in self.types() {
202 ty.visit(&mut f);
203 }
204 }
205
206 #[cfg(feature = "visit-mut")]
207 pub fn visit_types_mut(&mut self, mut f: impl FnMut(&mut Type)) {
208 for ty in self.types_mut() {
209 ty.visit_mut(&mut f);
210 }
211 }
212}