miden_assembly_syntax/ast/attribute/meta/
kv.rs

1use alloc::collections::BTreeMap;
2use core::borrow::Borrow;
3
4use miden_debug_types::{SourceSpan, Spanned};
5
6use super::MetaExpr;
7use crate::ast::Ident;
8
9/// Represents the metadata of a key-value [crate::ast::Attribute], i.e. `@props(key = value)`
10#[derive(Clone)]
11pub struct MetaKeyValue {
12    pub span: SourceSpan,
13    /// The name of the key-value dictionary
14    pub name: Ident,
15    /// The set of key-value pairs provided as arguments to this attribute
16    pub items: BTreeMap<Ident, MetaExpr>,
17}
18
19impl Spanned for MetaKeyValue {
20    #[inline(always)]
21    fn span(&self) -> SourceSpan {
22        self.span
23    }
24}
25
26impl MetaKeyValue {
27    pub fn new<K, V, I>(name: Ident, items: I) -> Self
28    where
29        I: IntoIterator<Item = (K, V)>,
30        K: Into<Ident>,
31        V: Into<MetaExpr>,
32    {
33        let items = items.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
34        Self { span: SourceSpan::default(), name, items }
35    }
36
37    pub fn with_span(mut self, span: SourceSpan) -> Self {
38        self.span = span;
39        self
40    }
41
42    /// Get the name of this metadata as a string
43    #[inline]
44    pub fn name(&self) -> &str {
45        self.name.as_str()
46    }
47
48    /// Get the name of this metadata as an [Ident]
49    #[inline]
50    pub fn id(&self) -> Ident {
51        self.name.clone()
52    }
53
54    /// Returns true if this metadata contains an entry for `key`
55    pub fn contains_key<Q>(&self, key: &Q) -> bool
56    where
57        Ident: Borrow<Q> + Ord,
58        Q: ?Sized + Ord,
59    {
60        self.items.contains_key(key)
61    }
62
63    /// Returns the value associated with `key`, if present in this metadata
64    pub fn get<Q>(&self, key: &Q) -> Option<&MetaExpr>
65    where
66        Ident: Borrow<Q> + Ord,
67        Q: ?Sized + Ord,
68    {
69        self.items.get(key)
70    }
71
72    /// Inserts a new key-value entry in this metadata
73    pub fn insert(&mut self, key: impl Into<Ident>, value: impl Into<MetaExpr>) {
74        self.items.insert(key.into(), value.into());
75    }
76
77    /// Removes the entry associated with `key`, if present in this metadata, and returns it
78    pub fn remove<Q>(&mut self, key: &Q) -> Option<MetaExpr>
79    where
80        Ident: Borrow<Q> + Ord,
81        Q: ?Sized + Ord,
82    {
83        self.items.remove(key)
84    }
85
86    /// Get an entry in the key-value map of this metadata for `key`
87    pub fn entry(
88        &mut self,
89        key: Ident,
90    ) -> alloc::collections::btree_map::Entry<'_, Ident, MetaExpr> {
91        self.items.entry(key)
92    }
93
94    /// Get an iterator over the the key-value items of this metadata
95    #[inline]
96    pub fn iter(&self) -> impl Iterator<Item = (&Ident, &MetaExpr)> {
97        self.items.iter()
98    }
99}
100
101impl IntoIterator for MetaKeyValue {
102    type Item = (Ident, MetaExpr);
103    type IntoIter = alloc::collections::btree_map::IntoIter<Ident, MetaExpr>;
104
105    #[inline]
106    fn into_iter(self) -> Self::IntoIter {
107        self.items.into_iter()
108    }
109}
110
111impl Eq for MetaKeyValue {}
112
113impl PartialEq for MetaKeyValue {
114    fn eq(&self, other: &Self) -> bool {
115        self.name == other.name && self.items == other.items
116    }
117}
118
119impl PartialOrd for MetaKeyValue {
120    #[inline]
121    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
122        Some(self.cmp(other))
123    }
124}
125
126impl Ord for MetaKeyValue {
127    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
128        self.name.cmp(&other.name).then_with(|| self.items.cmp(&other.items))
129    }
130}
131
132impl core::hash::Hash for MetaKeyValue {
133    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
134        self.name.hash(state);
135        self.items.hash(state);
136    }
137}