miden_assembly_syntax/ast/attribute/meta/
list.rs

1use alloc::vec::Vec;
2
3use miden_core::utils::{
4    ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
5};
6use miden_debug_types::{SourceSpan, Spanned};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use super::MetaExpr;
11use crate::ast::Ident;
12
13/// Represents the metadata of a named list [crate::ast::Attribute], i.e. `@name(item0, .., itemN)`
14#[derive(Debug, Clone)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16pub struct MetaList {
17    #[cfg_attr(feature = "serde", serde(skip, default))]
18    pub span: SourceSpan,
19    /// The identifier used as the name of this attribute
20    pub name: Ident,
21    /// The list of items representing the value of this attribute - will always contain at least
22    /// one element when parsed.
23    pub items: Vec<MetaExpr>,
24}
25
26impl Spanned for MetaList {
27    #[inline(always)]
28    fn span(&self) -> SourceSpan {
29        self.span
30    }
31}
32
33impl MetaList {
34    pub fn new<I>(name: Ident, items: I) -> Self
35    where
36        I: IntoIterator<Item = MetaExpr>,
37    {
38        Self {
39            span: SourceSpan::default(),
40            name,
41            items: items.into_iter().collect(),
42        }
43    }
44
45    pub fn with_span(mut self, span: SourceSpan) -> Self {
46        self.span = span;
47        self
48    }
49
50    /// Get the name of this attribute as a string
51    pub fn name(&self) -> &str {
52        self.name.as_str()
53    }
54
55    /// Get the name of this attribute as an [Ident]
56    pub fn id(&self) -> Ident {
57        self.name.clone()
58    }
59
60    /// Returns true if the metadata list is empty
61    #[inline]
62    pub fn is_empty(&self) -> bool {
63        self.items.is_empty()
64    }
65
66    /// Returns the number of items in the metadata list
67    #[inline]
68    pub fn len(&self) -> usize {
69        self.items.len()
70    }
71
72    /// Get the metadata list as a slice
73    #[inline]
74    pub fn as_slice(&self) -> &[MetaExpr] {
75        self.items.as_slice()
76    }
77
78    /// Get the metadata list as a mutable slice
79    #[inline]
80    pub fn as_mut_slice(&mut self) -> &mut [MetaExpr] {
81        self.items.as_mut_slice()
82    }
83}
84
85impl Eq for MetaList {}
86
87impl PartialEq for MetaList {
88    fn eq(&self, other: &Self) -> bool {
89        self.name == other.name && self.items == other.items
90    }
91}
92
93impl PartialOrd for MetaList {
94    #[inline]
95    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
96        Some(self.cmp(other))
97    }
98}
99
100impl Ord for MetaList {
101    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
102        self.name.cmp(&other.name).then_with(|| self.items.cmp(&other.items))
103    }
104}
105
106impl core::hash::Hash for MetaList {
107    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
108        self.name.hash(state);
109        self.items.hash(state);
110    }
111}
112
113#[cfg(feature = "arbitrary")]
114impl proptest::arbitrary::Arbitrary for MetaList {
115    type Parameters = ();
116
117    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
118        use proptest::{arbitrary::any, strategy::Strategy};
119
120        let name = any::<Ident>();
121        let items = proptest::collection::vec(any::<MetaExpr>(), 1..3);
122        (name, items)
123            .prop_map(|(name, items)| Self { span: SourceSpan::UNKNOWN, name, items })
124            .boxed()
125    }
126
127    type Strategy = proptest::prelude::BoxedStrategy<Self>;
128}
129
130impl Serializable for MetaList {
131    fn write_into<W: ByteWriter>(&self, target: &mut W) {
132        self.name.write_into(target);
133        self.items.write_into(target);
134    }
135}
136
137impl Deserializable for MetaList {
138    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
139        let name = Ident::read_from(source)?;
140        let items = Vec::read_from(source)?;
141
142        Ok(Self { span: SourceSpan::UNKNOWN, name, items })
143    }
144}