morphir_core/ir/v4/
annotation.rs1use serde::ser::{SerializeMap, Serializer};
10use serde::{Deserialize, Deserializer, Serialize};
11use std::ops::Deref;
12
13use super::linked_metadata::MetadataScope;
14use super::linked_metadata_scan::StandaloneMetadata;
15use super::value::Value;
16use crate::naming::{FQName, Name};
17use crate::node_address::NodeUri;
18
19#[derive(Debug, Clone, Default, PartialEq)]
24pub struct Annotations {
25 pub entries: Vec<Annotation>,
27 pub metadata: Option<Box<MetadataScope>>,
29}
30
31impl Annotations {
32 pub fn parse_unresolved(value: &serde_json::Value) -> Result<Self, String> {
35 super::serde_document::decode_annotations_value(value, "annotations")
36 .map_err(|error| error.message)
37 }
38
39 pub fn new(entries: Vec<Annotation>) -> Self {
41 Self {
42 entries,
43 metadata: None,
44 }
45 }
46
47 pub fn is_empty(&self) -> bool {
49 self.entries.is_empty() && self.metadata.is_none()
50 }
51}
52
53impl Deref for Annotations {
54 type Target = [Annotation];
55
56 fn deref(&self) -> &Self::Target {
57 &self.entries
58 }
59}
60
61impl From<Vec<Annotation>> for Annotations {
62 fn from(entries: Vec<Annotation>) -> Self {
63 Self::new(entries)
64 }
65}
66
67impl PartialEq<Vec<Annotation>> for Annotations {
68 fn eq(&self, other: &Vec<Annotation>) -> bool {
69 self.metadata.is_none() && self.entries == *other
70 }
71}
72
73impl Serialize for Annotations {
74 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
75 if let Some(metadata) = &self.metadata {
76 let mut map = serializer.serialize_map(None)?;
77 if let Some(context) = &metadata.context {
78 map.serialize_entry("@context", context)?;
79 }
80 if !self.entries.is_empty() {
81 map.serialize_entry("entries", &self.entries)?;
82 }
83 if !metadata.facts.is_empty() {
84 map.serialize_entry("facts", &metadata.facts)?;
85 }
86 map.end()
87 } else {
88 self.entries.serialize(serializer)
89 }
90 }
91}
92
93impl<'de> Deserialize<'de> for Annotations {
94 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
95 let value = serde_json::Value::deserialize(deserializer)?;
96 let mut decoded = super::serde_document::decode_annotations_value(&value, "")
97 .map_err(super::serde_tagged::carry)?;
98 decoded
99 .validate_standalone()
100 .map_err(serde::de::Error::custom)?;
101 Ok(decoded)
102 }
103}
104
105#[derive(Debug, Clone, PartialEq)]
107pub enum Annotation {
108 Compact { name: FQName, text: Option<String> },
110 Structured {
112 name: FQName,
113 args: Vec<AnnotationArgument>,
114 },
115 LinkedCompact {
117 authored_name: String,
119 declaration: NodeUri,
121 },
122 LinkedStructured {
124 authored_name: String,
126 declaration: NodeUri,
128 args: Vec<AnnotationArgument>,
130 },
131 PendingCompact { authored_name: String },
133 PendingStructured {
135 authored_name: String,
136 args: Vec<AnnotationArgument>,
137 },
138}
139
140#[derive(Debug, Clone, PartialEq)]
142pub enum AnnotationArgument {
143 Positional(Value),
145 Named { name: Name, value: Value },
147}
148
149impl Serialize for Annotation {
150 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
151 match self {
152 Annotation::Compact { name, text: None } => {
153 serializer.serialize_str(&name.to_canonical_string())
154 }
155 Annotation::Compact {
156 name,
157 text: Some(text),
158 } => serializer.serialize_str(&format!("{}:{text}", name.to_canonical_string())),
159 Annotation::Structured { name, args } => {
160 let mut map = serializer.serialize_map(None)?;
161 map.serialize_entry("name", &name.to_canonical_string())?;
162 if !args.is_empty() {
163 map.serialize_entry("arguments", args)?;
164 }
165 map.end()
166 }
167 Annotation::LinkedCompact { authored_name, .. }
168 | Annotation::PendingCompact { authored_name } => {
169 serializer.serialize_str(authored_name)
170 }
171 Annotation::LinkedStructured {
172 authored_name,
173 args,
174 ..
175 }
176 | Annotation::PendingStructured {
177 authored_name,
178 args,
179 } => {
180 let mut map = serializer.serialize_map(None)?;
181 map.serialize_entry("name", authored_name)?;
182 if !args.is_empty() {
183 map.serialize_entry("arguments", args)?;
184 }
185 map.end()
186 }
187 }
188 }
189}
190
191impl Serialize for AnnotationArgument {
192 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
193 match self {
194 AnnotationArgument::Positional(value) => value.serialize(serializer),
195 AnnotationArgument::Named { name, value } => {
196 let mut map = serializer.serialize_map(Some(2))?;
197 map.serialize_entry("name", &name.to_canonical_string())?;
198 map.serialize_entry("value", value)?;
199 map.end()
200 }
201 }
202 }
203}