miden_assembly/ast/attribute/meta/
kv.rs

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