credence_lib/render/
annotations.rs1use super::{
2 super::{configuration::*, resolve::*},
3 renderer::*,
4};
5
6use {
7 bytestring::*,
8 compris::{normal::*, parse::Parser, resolve::*, *},
9 kutil_std::{collections::*, string::*},
10};
11
12#[derive(Clone, Debug, Default, Resolve)]
18pub struct Annotations {
19 #[resolve]
21 pub created: Option<ResolveDateTime>,
22
23 #[resolve]
25 pub updated: Option<ResolveDateTime>,
26
27 #[resolve]
29 pub renderer: Option<Renderer>,
30
31 #[resolve]
33 pub template: Option<ByteString>,
34
35 #[resolve]
37 pub variables: FastHashMap<ByteString, Value>,
38
39 #[resolve]
41 pub headers: FastHashMap<ByteString, ByteString>,
42
43 #[resolve(other_keys)]
45 pub other: FastHashMap<ByteString, Value>,
46}
47
48impl Annotations {
49 pub fn renderer(&self, configuration: &RenderConfiguration) -> Renderer {
51 self.renderer.clone().unwrap_or(configuration.default_renderer)
52 }
53
54 pub fn template<'own>(&'own self, configuration: &'own RenderConfiguration) -> &'own str {
56 self.template.as_ref().unwrap_or(&configuration.default_template)
57 }
58
59 pub fn parse(identifier: &str, representation: &str, format: Format) -> Self {
61 match Parser::new(format).with_try_unsigned_integers(true).parse_from_string(representation) {
62 Ok(annotations) => match Resolve::<_, CommonResolveContext, CommonResolveError>::resolve(&annotations) {
63 Ok(annotations) => {
64 if let Some(annotations) = annotations {
65 return annotations;
66 }
67 }
68
69 Err(error) => tracing::error!("{}: {}", identifier, error),
70 },
71
72 Err(error) => tracing::error!("{}: {}", identifier, error),
73 }
74
75 Self::default()
76 }
77
78 pub fn traverse_variable(&self, keys: &RefValuePath<'_>) -> Option<&Value> {
80 if !keys.is_empty() {
81 if let Value::Text(first_key) = &keys[0] {
82 if let Some(first_value) = self.variables.get(&first_key.value) {
83 let keys = keys[1..].iter().map(|value| *value);
84 return first_value.traverse(keys);
85 }
86 }
87 }
88
89 None
90 }
91}
92
93impl AnnotationsConfiguration {
94 pub fn split<'content>(&self, identifier: &str, content: &'content str) -> (Annotations, &'content str) {
96 let start_delimiter: &str = &self.start_delimiter;
97 if content.starts_with(start_delimiter) {
98 let end_delimiter: &str = &self.end_delimiter;
99 if let Some((properties, content)) =
100 content[start_delimiter.len()..].split_once_ignore_escaped(end_delimiter)
101 {
102 let annotations = properties.unescape(end_delimiter);
104 let mut annotations = annotations.as_str();
105
106 let format = {
107 match annotations.split_once('\n') {
109 Some((format, annotations_after_format)) => {
110 let format_result = format.parse();
111 annotations = annotations_after_format;
112 format_result.unwrap_or(self.default_format.value.into())
113 }
114
115 None => self.default_format.value.into(),
116 }
117 };
118
119 let annotations = Annotations::parse(identifier, annotations, format);
120 return (annotations, content);
121 }
122 }
123
124 (Annotations::default(), content)
125 }
126}