cedar_policy_core/ast/
annotation.rs1use std::collections::BTreeMap;
18
19use educe::Educe;
20use serde::{Deserialize, Serialize};
21use smol_str::SmolStr;
22
23use crate::parser::Loc;
24
25use super::AnyId;
26
27#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
29#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
30pub struct Annotations(BTreeMap<AnyId, Annotation>);
31
32impl std::fmt::Display for Annotations {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 for (k, v) in &self.0 {
35 writeln!(f, "@{k}({v})")?
36 }
37 Ok(())
38 }
39}
40
41impl Annotations {
42 pub fn new() -> Self {
44 Self(BTreeMap::new())
45 }
46
47 pub fn get(&self, key: &AnyId) -> Option<&Annotation> {
49 self.0.get(key)
50 }
51
52 pub fn iter(&self) -> impl Iterator<Item = (&AnyId, &Annotation)> {
54 self.0.iter()
55 }
56
57 pub fn is_empty(&self) -> bool {
59 self.0.is_empty()
60 }
61}
62
63#[derive(Debug)]
65pub struct IntoIter(std::collections::btree_map::IntoIter<AnyId, Annotation>);
66
67impl Iterator for IntoIter {
68 type Item = (AnyId, Annotation);
69
70 fn next(&mut self) -> Option<Self::Item> {
71 self.0.next()
72 }
73}
74
75impl IntoIterator for Annotations {
76 type Item = (AnyId, Annotation);
77
78 type IntoIter = IntoIter;
79
80 fn into_iter(self) -> Self::IntoIter {
81 IntoIter(self.0.into_iter())
82 }
83}
84
85impl Default for Annotations {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl FromIterator<(AnyId, Annotation)> for Annotations {
92 fn from_iter<T: IntoIterator<Item = (AnyId, Annotation)>>(iter: T) -> Self {
93 Self(BTreeMap::from_iter(iter))
94 }
95}
96
97impl From<BTreeMap<AnyId, Annotation>> for Annotations {
98 fn from(value: BTreeMap<AnyId, Annotation>) -> Self {
99 Self(value)
100 }
101}
102
103#[derive(Educe, Clone, Debug, Serialize, Deserialize, Default)]
105#[educe(Hash, PartialEq, Eq, PartialOrd, Ord)]
106#[serde(transparent)]
107#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
108#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
109pub struct Annotation {
110 pub val: SmolStr,
112 #[serde(skip)]
115 #[educe(Hash(ignore))]
116 #[educe(PartialEq(ignore))]
117 #[educe(PartialOrd(ignore))]
118 pub loc: Option<Loc>,
119}
120
121impl std::fmt::Display for Annotation {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 write!(f, "\"{}\"", self.val.escape_debug())
124 }
125}
126
127impl Annotation {
128 pub fn with_optional_value(val: Option<SmolStr>, loc: Option<Loc>) -> Self {
133 Self {
134 val: val.unwrap_or_default(),
135 loc,
136 }
137 }
138}
139
140impl AsRef<str> for Annotation {
141 fn as_ref(&self) -> &str {
142 &self.val
143 }
144}
145
146#[cfg(feature = "arbitrary")]
147impl<'a> arbitrary::Arbitrary<'a> for Annotation {
148 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
149 Ok(Self {
150 val: u.arbitrary::<&str>()?.into(),
151 loc: None,
152 })
153 }
154
155 fn size_hint(depth: usize) -> (usize, Option<usize>) {
156 <&str as arbitrary::Arbitrary>::size_hint(depth)
157 }
158}