fmi_schema/fmi3/variable/
dimension.rs1use hard_xml::{XmlRead, XmlWrite};
3
4#[derive(Clone, PartialEq, Debug)]
5pub enum Dimension {
6 Fixed(u64),
9 Variable(u32),
17}
18
19impl Dimension {
20 pub fn as_fixed(&self) -> Option<u64> {
21 match self {
22 Dimension::Fixed(size) => Some(*size),
23 Dimension::Variable(_) => None,
24 }
25 }
26
27 pub fn as_variable(&self) -> Option<u32> {
28 match self {
29 Dimension::Fixed(_) => None,
30 Dimension::Variable(value_reference) => Some(*value_reference),
31 }
32 }
33}
34
35impl Default for Dimension {
36 fn default() -> Self {
37 Self::Fixed(1)
38 }
39}
40
41#[derive(hard_xml::XmlRead, hard_xml::XmlWrite)]
42#[xml(tag = "Dimension")]
43struct Inner {
44 #[xml(attr = "start")]
45 start: Option<u64>,
46 #[xml(attr = "valueReference")]
47 value_reference: Option<u32>,
48}
49
50impl<'a> XmlRead<'a> for Dimension {
51 fn from_reader(reader: &mut hard_xml::XmlReader<'a>) -> hard_xml::XmlResult<Self> {
52 let Inner {
53 start,
54 value_reference,
55 } = Inner::from_reader(reader)?;
56
57 match (start, value_reference) {
58 (Some(_), Some(_)) => Err(hard_xml::XmlExtendedError::DuplicateAttribute(
59 "Dimension cannot have both 'start' and 'valueReference' attributes".into(),
60 )
61 .into()),
62 (None, None) => Err(hard_xml::XmlError::MissingField {
63 name: "Dimension".into(),
64 field: "either 'start' or 'valueReference'".into(),
65 }),
66 (Some(start), None) => Ok(Dimension::Fixed(start)),
67 (None, Some(value_reference)) => Ok(Dimension::Variable(value_reference)),
68 }
69 }
70}
71
72impl XmlWrite for Dimension {
73 fn to_writer<W: std::io::Write>(
74 &self,
75 writer: &mut hard_xml::XmlWriter<W>,
76 ) -> hard_xml::XmlResult<()> {
77 match self {
78 Dimension::Fixed(fixed) => Inner {
79 start: Some(*fixed),
80 value_reference: None,
81 },
82 Dimension::Variable(variable) => Inner {
83 start: None,
84 value_reference: Some(*variable),
85 },
86 }
87 .to_writer(writer)
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[derive(Default, PartialEq, Debug, hard_xml::XmlRead, hard_xml::XmlWrite)]
96 #[xml(tag = "TestVar")]
97 pub struct TestVar {
98 #[xml(child = "Dimension")]
99 pub dimensions: Vec<Dimension>,
100 }
101 #[test]
102 fn test_dim_de() {
103 let _ = env_logger::builder()
104 .is_test(true)
105 .format_timestamp(None)
106 .try_init();
107
108 let xml = r#"<TestVar>
109 <Dimension valueReference="2"/>
110 <Dimension start="2"/>
111 </TestVar>"#;
112 let var = TestVar::from_str(xml).unwrap();
113
114 assert_eq!(var.dimensions.len(), 2);
115 assert_eq!(var.dimensions[0], Dimension::Variable(2));
116 assert_eq!(var.dimensions[1], Dimension::Fixed(2));
117 }
118
119 #[test]
120 fn test_dim_roundtrip() {
121 let var = TestVar {
122 dimensions: vec![Dimension::Fixed(2), Dimension::Variable(0)],
123 };
124 let serialized = var.to_string().unwrap();
125 let deserialized = TestVar::from_str(&serialized).unwrap();
126 assert_eq!(var, deserialized);
127 }
128}