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