acdc_parser/model/
metadata.rs1use serde::Serialize;
4
5use super::anchor::Anchor;
6use super::attributes::{AttributeValue, ElementAttributes};
7use super::attribution::{Attribution, CiteTitle};
8use super::location::Location;
9use super::substitution::SubstitutionSpec;
10
11pub type Role = String;
12
13#[derive(Clone, Debug, Default, PartialEq, Serialize)]
15#[non_exhaustive]
16pub struct BlockMetadata {
17 #[serde(default, skip_serializing_if = "ElementAttributes::is_empty")]
18 pub attributes: ElementAttributes,
19 #[serde(default, skip_serializing)]
20 pub positional_attributes: Vec<String>,
21 #[serde(default, skip_serializing_if = "Vec::is_empty")]
22 pub roles: Vec<Role>,
23 #[serde(default, skip_serializing_if = "Vec::is_empty")]
24 pub options: Vec<String>,
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub style: Option<String>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub id: Option<Anchor>,
29 #[serde(default, skip_serializing_if = "Vec::is_empty")]
30 pub anchors: Vec<Anchor>,
31 #[serde(default, skip_serializing_if = "Option::is_none")]
38 pub substitutions: Option<SubstitutionSpec>,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub attribution: Option<Attribution>,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
42 pub citetitle: Option<CiteTitle>,
43 #[serde(skip)]
44 pub location: Option<Location>,
45}
46
47impl BlockMetadata {
48 #[must_use]
50 pub fn new() -> Self {
51 Self::default()
52 }
53
54 #[must_use]
56 pub fn with_attributes(mut self, attributes: ElementAttributes) -> Self {
57 self.attributes = attributes;
58 self
59 }
60
61 #[must_use]
63 pub fn with_options(mut self, options: Vec<String>) -> Self {
64 self.options = options;
65 self
66 }
67
68 #[must_use]
70 pub fn with_roles(mut self, roles: Vec<Role>) -> Self {
71 self.roles = roles;
72 self
73 }
74
75 #[must_use]
77 pub fn with_style(mut self, style: Option<String>) -> Self {
78 self.style = style;
79 self
80 }
81
82 #[must_use]
84 pub fn with_id(mut self, id: Option<Anchor>) -> Self {
85 self.id = id;
86 self
87 }
88
89 pub fn move_positional_attributes_to_attributes(&mut self) {
90 for positional_attribute in self.positional_attributes.drain(..) {
91 self.attributes
92 .insert(positional_attribute, AttributeValue::None);
93 }
94 }
95
96 pub fn set_attributes(&mut self, attributes: ElementAttributes) {
97 self.attributes = attributes;
98 }
99
100 #[must_use]
101 pub fn is_default(&self) -> bool {
102 self.roles.is_empty()
103 && self.options.is_empty()
104 && self.style.is_none()
105 && self.id.is_none()
106 && self.anchors.is_empty()
107 && self.attributes.is_empty()
108 && self.positional_attributes.is_empty()
109 && self.substitutions.is_none()
110 && self.attribution.is_none()
111 && self.citetitle.is_none()
112 }
113
114 #[tracing::instrument(level = "debug")]
115 pub fn merge(&mut self, other: &BlockMetadata) {
116 self.attributes.merge(other.attributes.clone());
117 self.positional_attributes
118 .extend(other.positional_attributes.clone());
119 self.roles.extend(other.roles.clone());
120 self.options.extend(other.options.clone());
121 if self.style.is_none() {
122 self.style.clone_from(&other.style);
123 }
124 if self.id.is_none() {
125 self.id.clone_from(&other.id);
126 }
127 self.anchors.extend(other.anchors.clone());
128 if self.substitutions.is_none() {
129 self.substitutions.clone_from(&other.substitutions);
130 }
131 if self.attribution.is_none() {
132 self.attribution.clone_from(&other.attribution);
133 }
134 if self.citetitle.is_none() {
135 self.citetitle.clone_from(&other.citetitle);
136 }
137 }
138}