cedar_policy_core/ast/
annotation.rsuse std::collections::BTreeMap;
use educe::Educe;
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
use crate::parser::Loc;
use super::AnyId;
#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Annotations(
#[serde(default)]
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
#[serde(with = "::serde_with::rust::maps_duplicate_key_is_error")]
BTreeMap<AnyId, Annotation>,
);
impl std::fmt::Display for Annotations {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (k, v) in &self.0 {
writeln!(f, "@{k}({v})")?
}
Ok(())
}
}
impl Annotations {
pub fn new() -> Self {
Self(BTreeMap::new())
}
pub fn get(&self, key: &AnyId) -> Option<&Annotation> {
self.0.get(key)
}
pub fn iter(&self) -> impl Iterator<Item = (&AnyId, &Annotation)> {
self.0.iter()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct IntoIter(std::collections::btree_map::IntoIter<AnyId, Annotation>);
impl Iterator for IntoIter {
type Item = (AnyId, Annotation);
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
impl IntoIterator for Annotations {
type Item = (AnyId, Annotation);
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
IntoIter(self.0.into_iter())
}
}
impl Default for Annotations {
fn default() -> Self {
Self::new()
}
}
impl FromIterator<(AnyId, Annotation)> for Annotations {
fn from_iter<T: IntoIterator<Item = (AnyId, Annotation)>>(iter: T) -> Self {
Self(BTreeMap::from_iter(iter))
}
}
impl From<BTreeMap<AnyId, Annotation>> for Annotations {
fn from(value: BTreeMap<AnyId, Annotation>) -> Self {
Self(value)
}
}
#[derive(Educe, Clone, Debug, Serialize, Deserialize, Default)]
#[educe(Hash, PartialEq, Eq, PartialOrd, Ord)]
#[serde(transparent)]
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
pub struct Annotation {
pub val: SmolStr,
#[serde(skip)]
#[educe(Hash(ignore))]
#[educe(PartialEq(ignore))]
#[educe(PartialOrd(ignore))]
pub loc: Option<Loc>,
}
impl std::fmt::Display for Annotation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\"{}\"", self.val.escape_debug())
}
}
impl Annotation {
pub fn with_optional_value(val: Option<SmolStr>, loc: Option<Loc>) -> Self {
Self {
val: val.unwrap_or_default(),
loc,
}
}
}
impl AsRef<str> for Annotation {
fn as_ref(&self) -> &str {
&self.val
}
}
#[cfg(feature = "protobufs")]
impl From<&crate::ast::proto::Annotation> for Annotation {
fn from(v: &crate::ast::proto::Annotation) -> Self {
Self {
val: v.val.clone().into(),
loc: None,
}
}
}
#[cfg(feature = "protobufs")]
impl From<&Annotation> for crate::ast::proto::Annotation {
fn from(v: &Annotation) -> Self {
Self {
val: v.val.to_string(),
}
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for Annotation {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self {
val: u.arbitrary::<&str>()?.into(),
loc: None,
})
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}