credence_lib/render/
annotations.rs

1use super::{
2    super::{configuration::*, resolve::*},
3    renderer::*,
4};
5
6use {
7    compris::{annotate::*, normal::*, parse::Parser, resolve::*, *},
8    kutil::std::{collections::*, immutable::*, string::*},
9};
10
11//
12// Annotations
13//
14
15/// Annotations.
16#[derive(Clone, Debug, Default, Resolve)]
17pub struct Annotations {
18    /// Created.
19    #[resolve]
20    pub created: Option<ResolveDateTime>,
21
22    /// Last updated.
23    #[resolve]
24    pub updated: Option<ResolveDateTime>,
25
26    /// Renderer.
27    #[resolve]
28    pub renderer: Option<Renderer>,
29
30    /// Template.
31    #[resolve]
32    pub template: Option<ByteString>,
33
34    /// Variables.
35    #[resolve]
36    pub variables: FastHashMap<ByteString, Variant<WithAnnotations>>,
37
38    /// Headers.
39    #[resolve]
40    pub headers: FastHashMap<ByteString, ByteString>,
41
42    /// Other.
43    #[resolve(other_keys)]
44    pub other: FastHashMap<ByteString, Variant<WithAnnotations>>,
45}
46
47impl Annotations {
48    /// Renderer.
49    pub fn renderer(&self, configuration: &RenderConfiguration) -> Renderer {
50        self.renderer.clone().unwrap_or(configuration.default_renderer)
51    }
52
53    /// Template.
54    pub fn template<'own>(&'own self, configuration: &'own RenderConfiguration) -> &'own str {
55        self.template.as_ref().unwrap_or(&configuration.default_template)
56    }
57
58    /// Parse.
59    pub fn parse(identifier: &str, representation: &str, format: Format) -> Self {
60        match Parser::new(format).with_try_unsigned_integers(true).parse_string::<WithAnnotations>(representation) {
61            Ok(annotations) => match annotations.resolve() {
62                Ok(annotations) => {
63                    return annotations;
64                }
65
66                Err(ResolveError::Missing) => {}
67
68                Err(error) => tracing::error!("{}: {}", identifier, error),
69            },
70
71            Err(error) => tracing::error!("{}: {}", identifier, error),
72        }
73
74        Self::default()
75    }
76
77    /// Traverse variable.
78    pub fn traverse_variable(&self, keys: &RefTraversal<'_, WithAnnotations>) -> Option<&Variant<WithAnnotations>> {
79        if !keys.is_empty() {
80            if let Variant::Text(first_key) = &keys[0]
81                && let Some(first_value) = self.variables.get(&first_key.inner)
82            {
83                let keys = keys[1..].iter().map(|variant| *variant);
84                return first_value.traverse(keys);
85            }
86        }
87
88        None
89    }
90}
91
92impl AnnotationsConfiguration {
93    /// Split [Annotations] from content.
94    pub fn split<'content>(&self, identifier: &str, content: &'content str) -> (Annotations, &'content str) {
95        let start_delimiter: &str = &self.start_delimiter;
96        if content.starts_with(start_delimiter) {
97            let end_delimiter: &str = &self.end_delimiter;
98            if let Some((properties, content)) =
99                content[start_delimiter.len()..].split_once_ignore_escaped(end_delimiter)
100            {
101                // Unescape end delimiter
102                let annotations = properties.unescape(end_delimiter);
103                let mut annotations = annotations.as_str();
104
105                let format = {
106                    // The format can be right after the start delimiter with a newline
107                    match annotations.split_once('\n') {
108                        Some((format, annotations_after_format)) => {
109                            let format_result = format.parse();
110                            annotations = annotations_after_format;
111                            format_result.unwrap_or(self.default_format.inner.into())
112                        }
113
114                        None => self.default_format.inner.into(),
115                    }
116                };
117
118                let annotations = Annotations::parse(identifier, annotations, format);
119                return (annotations, content);
120            }
121        }
122
123        (Default::default(), content)
124    }
125}