collagen/fibroblast/tags/
mod.rs1pub(crate) mod any_child_tag;
34pub(crate) mod container_tag;
35pub(crate) mod element;
36pub(crate) mod font_tag;
37pub(crate) mod generic_tag;
38pub(crate) mod image_tag;
39pub(crate) mod nested_svg_tag;
40pub mod root_tag;
41pub(crate) mod text_tag;
42pub(crate) mod validation;
43
44use self::element::XmlAttrs;
45use crate::from_json::decoding_error::{InvalidSchemaError, InvalidSchemaErrorList};
46pub(super) use crate::{
47 fibroblast::data_types::DecodingContext, to_svg::svg_writable::ClgnDecodingResult,
48};
49pub use any_child_tag::AnyChildTag;
50use any_child_tag::UnvalidatedAnyChildTag;
51pub use container_tag::ContainerTag;
52pub use font_tag::FontTag;
53pub use generic_tag::GenericTag;
54pub use image_tag::ImageTag;
55pub use nested_svg_tag::NestedSvgTag;
56use serde::{Deserialize, Serialize};
57use std::{fmt, sync::LazyLock};
58use validation::Validatable;
59
60pub(crate) static EMPTY_ATTRS: LazyLock<XmlAttrs> = LazyLock::new(|| XmlAttrs(Vec::new()));
64
65#[derive(Serialize, Deserialize)]
67#[serde(transparent)]
68pub struct Extras(serde_json::Map<String, serde_json::Value>);
69
70impl fmt::Debug for Extras {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(f, "{:?}", self.0)
73 }
74}
75
76impl Extras {
77 pub(crate) fn map(&self) -> &serde_json::Map<String, serde_json::Value> {
78 &self.0
79 }
80
81 pub(crate) fn ensure_empty(&self, for_tag: &'static str) -> Result<(), InvalidSchemaError> {
82 if !self.0.is_empty() {
83 return Err(InvalidSchemaError::unexpected_keys(
84 for_tag,
85 self.0.keys().cloned().collect(),
86 ));
87 }
88
89 Ok(())
90 }
91}
92
93#[derive(Debug, Default, Clone, Serialize, Deserialize)]
99#[serde(transparent)]
100pub struct DeXmlAttrs {
101 #[serde(skip_serializing_if = "Option::is_none")]
104 attrs: Option<XmlAttrs>,
105}
106
107impl AsRef<XmlAttrs> for DeXmlAttrs {
108 fn as_ref(&self) -> &XmlAttrs {
109 self.attrs.as_ref().unwrap_or(&EMPTY_ATTRS)
110 }
111}
112
113#[derive(Debug, Clone, Serialize)]
117#[serde(transparent)]
118pub(crate) struct DeChildTags {
119 #[serde(skip_serializing_if = "Option::is_none")]
120 pub(crate) children: Option<Vec<AnyChildTag>>,
121}
122
123impl AsRef<[AnyChildTag]> for DeChildTags {
124 fn as_ref(&self) -> &[AnyChildTag] {
125 self.children.as_deref().unwrap_or(&[])
126 }
127}
128
129#[derive(Deserialize)]
132#[serde(untagged)]
133enum UnvalidatedDeChildTagsWrapper {
134 One(UnvalidatedAnyChildTag),
135 Multiple(Vec<UnvalidatedAnyChildTag>),
136}
137
138#[derive(Debug, Deserialize)]
139#[serde(from = "Option<UnvalidatedDeChildTagsWrapper>")]
140pub(crate) struct UnvalidatedDeChildTags {
141 #[serde(default)]
142 pub(crate) children: Option<Vec<UnvalidatedAnyChildTag>>,
143}
144
145impl From<Option<UnvalidatedDeChildTagsWrapper>> for UnvalidatedDeChildTags {
146 fn from(children: Option<UnvalidatedDeChildTagsWrapper>) -> Self {
147 Self {
148 children: children.map(|children| match children {
149 UnvalidatedDeChildTagsWrapper::One(one) => vec![one],
150 UnvalidatedDeChildTagsWrapper::Multiple(multiple) => multiple,
151 }),
152 }
153 }
154}
155
156impl Validatable for UnvalidatedDeChildTags {
157 type Validated = DeChildTags;
158
159 fn into_validated(self, errors: &mut InvalidSchemaErrorList) -> Result<DeChildTags, ()> {
160 Ok(DeChildTags {
161 children: self
162 .children
163 .map(|c| {
164 c.into_iter()
165 .map(|child| child.into_validated(errors))
166 .collect::<Result<Vec<_>, _>>()
167 }) .transpose()?,
169 })
170 }
171}