biodivine_lib_param_bn/_impl_annotations/
_impl_writer.rs1use crate::_impl_annotations::{ALPHANUMERIC, validate_path_segment};
2use crate::ModelAnnotation;
3use std::fmt::{Display, Formatter};
4
5impl Display for ModelAnnotation {
6 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
7 self.fmt_with_path(&mut Vec::new(), f)
8 }
9}
10
11fn fmt_path(mut path: &[&str], f: &mut Formatter<'_>) -> std::fmt::Result {
14 while !path.is_empty() {
15 validate_path_segment(path[0]);
17 if ALPHANUMERIC.is_match(path[0]) {
18 write!(f, "{}:", path[0])?;
20 } else {
21 write!(f, "`{}`:", path[0])?;
23 }
24 path = &path[1..];
25 }
26 Ok(())
27}
28
29impl ModelAnnotation {
30 fn fmt_with_path<'a>(
38 &'a self,
39 path: &mut Vec<&'a str>,
40 f: &mut Formatter<'_>,
41 ) -> std::fmt::Result {
42 if let Some(value) = self.value.as_ref() {
43 if value.is_empty() {
44 write!(f, "#!")?;
47 fmt_path(path, f)?;
48 writeln!(f)?;
49 } else {
50 for line in value.lines() {
52 write!(f, "#!")?; fmt_path(path, f)?; let has_escape_sequence = line.starts_with("#`") && line.ends_with("`#");
58 let mut chars = line.chars();
59 let first_whitespace =
62 chars.next().map(|it| it.is_whitespace()).unwrap_or(false);
63 let last_whitespace =
64 chars.last().map(|it| it.is_whitespace()).unwrap_or(false);
65 let has_whitespace = first_whitespace || last_whitespace;
66 if line.contains(':') || has_escape_sequence || has_whitespace {
67 writeln!(f, "#`{}`#", line)?;
68 } else {
69 writeln!(f, "{}", line)?;
70 }
71 }
72 }
73 }
74
75 let mut keys = self.inner.keys().collect::<Vec<_>>();
77 keys.sort();
78 for key in keys {
79 path.push(key.as_str());
80 let child = self.inner.get(key).unwrap();
81 child.fmt_with_path(path, f)?;
82 path.pop();
83 }
84 Ok(())
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use crate::ModelAnnotation;
91
92 #[test]
93 pub fn annotation_read_write_test() {
94 let mut annotations = ModelAnnotation::new();
95 annotations.ensure_value::<&str>(&[], "hello");
97 annotations.ensure_value(&["name"], "Model name");
99 annotations.ensure_value(&["var", "", "x"], "");
101 annotations.ensure_value(&["var {list}"], "Hello: there");
103 annotations.ensure_value(&["multi_line"], " Hello\n\nWorld: #`Some escaped text`#.");
105
106 let string = annotations.to_string();
107 let parsed = ModelAnnotation::from_model_string(string.as_str());
108
109 assert_eq!(annotations, parsed);
110 }
111}