syn_solidity/type/
array.rs

1use crate::{Expr, Lit, LitNumber, Spanned, Type};
2use proc_macro2::Span;
3use std::{
4    fmt,
5    hash::{Hash, Hasher},
6};
7use syn::{
8    Result, bracketed,
9    parse::{Parse, ParseStream},
10    token::Bracket,
11};
12
13/// An array type.
14#[derive(Clone)]
15pub struct TypeArray {
16    pub ty: Box<Type>,
17    pub bracket_token: Bracket,
18    pub size: Option<Box<Expr>>,
19}
20
21impl PartialEq for TypeArray {
22    fn eq(&self, other: &Self) -> bool {
23        self.ty == other.ty && self.size() == other.size()
24    }
25}
26
27impl Eq for TypeArray {}
28
29impl Hash for TypeArray {
30    fn hash<H: Hasher>(&self, state: &mut H) {
31        self.ty.hash(state);
32        self.size().hash(state);
33    }
34}
35
36impl fmt::Display for TypeArray {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        self.ty.fmt(f)?;
39        f.write_str("[")?;
40        if let Some(s) = self.size_lit() {
41            f.write_str(s.base10_digits())?;
42        }
43        f.write_str("]")
44    }
45}
46
47impl fmt::Debug for TypeArray {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.debug_tuple("TypeArray").field(&self.ty).field(&self.size()).finish()
50    }
51}
52
53impl Parse for TypeArray {
54    fn parse(input: ParseStream<'_>) -> Result<Self> {
55        let ty = input.parse()?;
56        Self::parse_nested(Box::new(ty), input)
57    }
58}
59
60impl Spanned for TypeArray {
61    fn span(&self) -> Span {
62        let span = self.ty.span();
63        span.join(self.bracket_token.span.join()).unwrap_or(span)
64    }
65
66    fn set_span(&mut self, span: Span) {
67        self.ty.set_span(span);
68        self.bracket_token = Bracket(span);
69        if let Some(size) = &mut self.size {
70            size.set_span(span);
71        }
72    }
73}
74
75impl TypeArray {
76    /// Returns the size of the array, or None if dynamic.
77    pub fn size(&self) -> Option<usize> {
78        self.size_lit().and_then(|s| s.base10_parse().ok())
79    }
80
81    /// Returns the size of the array, or None if dynamic.
82    pub fn size_lit(&self) -> Option<&LitNumber> {
83        self.size.as_ref().and_then(|s| match &**s {
84            Expr::Lit(Lit::Number(n)) => Some(n),
85            _ => None,
86        })
87    }
88
89    /// See [`Type::is_abi_dynamic`].
90    pub fn is_abi_dynamic(&self) -> bool {
91        match self.size {
92            Some(_) => self.ty.is_abi_dynamic(),
93            None => true,
94        }
95    }
96
97    /// Parses an array type from the given input stream, wrapping `ty` with it.
98    pub fn parse_nested(ty: Box<Type>, input: ParseStream<'_>) -> Result<Self> {
99        let content;
100        Ok(Self {
101            ty,
102            bracket_token: bracketed!(content in input),
103            size: { if content.is_empty() { None } else { Some(content.parse()?) } },
104        })
105    }
106}