Skip to main content

fmi_schema/fmi3/
variable_dependency.rs

1use std::{fmt::Display, str::FromStr};
2
3use crate::utils::AttrList;
4
5use super::Annotations;
6
7#[derive(Default, PartialEq, Debug)]
8pub enum DependenciesKind {
9    #[default]
10    Dependent,
11    Constant,
12    Fixed,
13    Tunable,
14    Discrete,
15}
16
17impl FromStr for DependenciesKind {
18    type Err = String;
19
20    fn from_str(s: &str) -> Result<Self, Self::Err> {
21        match s {
22            "dependent" => Ok(DependenciesKind::Dependent),
23            "constant" => Ok(DependenciesKind::Constant),
24            "fixed" => Ok(DependenciesKind::Fixed),
25            "tunable" => Ok(DependenciesKind::Tunable),
26            "discrete" => Ok(DependenciesKind::Discrete),
27            _ => Err(format!("Invalid DependenciesKind: {}", s)),
28        }
29    }
30}
31
32impl Display for DependenciesKind {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        let s = match self {
35            DependenciesKind::Dependent => "dependent",
36            DependenciesKind::Constant => "constant",
37            DependenciesKind::Fixed => "fixed",
38            DependenciesKind::Tunable => "tunable",
39            DependenciesKind::Discrete => "discrete",
40        };
41        write!(f, "{}", s)
42    }
43}
44
45#[derive(Default, PartialEq, Debug)]
46pub struct Fmi3Unknown {
47    pub annotations: Option<Annotations>,
48    pub value_reference: u32,
49    pub dependencies: Option<AttrList<u32>>,
50    pub dependencies_kind: Option<AttrList<DependenciesKind>>,
51}
52
53impl<'__input> ::hard_xml::XmlRead<'__input> for Fmi3Unknown {
54    fn from_reader(reader: &mut ::hard_xml::XmlReader<'__input>) -> ::hard_xml::XmlResult<Self> {
55        use ::hard_xml::XmlError;
56        use ::hard_xml::xmlparser::{ElementEnd, Token};
57        ::hard_xml::log_start_reading!(Fmi3Unknown_);
58        let mut __self_annotations = None;
59        let mut __self_value_reference = None;
60        let mut __self_dependencies = None;
61        let mut __self_dependencies_kind = None;
62
63        let tag = reader
64            .find_element_start(None)?
65            .expect("Expected start element");
66        let _ = reader.next().unwrap()?; // Move to attributes or end
67
68        while let Some((__key, __value)) = reader.find_attribute()? {
69            match __key {
70                "valueReference" => {
71                    ::hard_xml::log_start_reading_field!(Fmi3Unknown_, value_reference);
72                    if __self_value_reference.is_some() {
73                        return ::std::result::Result::Err(
74                            ::hard_xml::XmlExtendedError::DuplicateAttribute(
75                                ("valueReference").into(),
76                            )
77                            .into(),
78                        );
79                    }
80                    __self_value_reference = Some(
81                        <u32 as std::str::FromStr>::from_str(&__value)
82                            .map_err(|e| XmlError::FromStr(e.into()))?,
83                    );
84                    ::hard_xml::log_finish_reading_field!(Fmi3Unknown_, value_reference);
85                }
86                "dependencies" => {
87                    ::hard_xml::log_start_reading_field!(Fmi3Unknown_, dependencies);
88                    if __self_dependencies.is_some() {
89                        return ::std::result::Result::Err(
90                            ::hard_xml::XmlExtendedError::DuplicateAttribute(
91                                ("dependencies").into(),
92                            )
93                            .into(),
94                        );
95                    }
96                    __self_dependencies = Some(
97                        <AttrList<u32> as std::str::FromStr>::from_str(&__value)
98                            .map_err(|e| XmlError::FromStr(e.into()))?,
99                    );
100                    ::hard_xml::log_finish_reading_field!(Fmi3Unknown_, dependencies);
101                }
102                "dependenciesKind" => {
103                    ::hard_xml::log_start_reading_field!(Fmi3Unknown_, dependencies_kind);
104                    if __self_dependencies_kind.is_some() {
105                        return ::std::result::Result::Err(
106                            ::hard_xml::XmlExtendedError::DuplicateAttribute(
107                                ("dependenciesKind").into(),
108                            )
109                            .into(),
110                        );
111                    }
112                    __self_dependencies_kind = Some(
113                        <AttrList<DependenciesKind> as std::str::FromStr>::from_str(&__value)
114                            .map_err(|e| XmlError::FromStr(e.into()))?,
115                    );
116                    ::hard_xml::log_finish_reading_field!(Fmi3Unknown_, dependencies_kind);
117                }
118                key => {
119                    return Err(XmlError::UnknownField {
120                        name: stringify!(Fmi3Unknown_).to_owned(),
121                        field: key.to_owned(),
122                    });
123                }
124            }
125        }
126        if let Token::ElementEnd {
127            end: ElementEnd::Empty,
128            ..
129        } = reader.next().unwrap()?
130        {
131            let __res = Fmi3Unknown {
132                annotations: __self_annotations,
133                value_reference: __self_value_reference.ok_or(XmlError::MissingField {
134                    name: stringify!(Fmi3Unknown_).to_owned(),
135                    field: stringify!(value_reference).to_owned(),
136                })?,
137                dependencies: __self_dependencies,
138                dependencies_kind: __self_dependencies_kind,
139            };
140            ::hard_xml::log_finish_reading!(Fmi3Unknown_);
141            return Ok(__res);
142        }
143        while let Some(__tag) = reader.find_element_start(Some(tag))? {
144            match __tag {
145                "Annotations" => {
146                    ::hard_xml::log_start_reading_field!(Fmi3Unknown_, annotations);
147                    if __self_annotations.is_some() {
148                        return ::std::result::Result::Err(
149                            ::hard_xml::XmlExtendedError::DuplicateElement(
150                                __tag.to_string().into(),
151                            )
152                            .into(),
153                        );
154                    }
155                    __self_annotations =
156                        Some(<Annotations as ::hard_xml::XmlRead>::from_reader(reader)?);
157                    ::hard_xml::log_finish_reading_field!(Fmi3Unknown_, annotations);
158                }
159                tag => {
160                    return Err(XmlError::UnknownField {
161                        name: stringify!(Fmi3Unknown_).to_owned(),
162                        field: tag.to_owned(),
163                    });
164                }
165            }
166        }
167        let __res = Fmi3Unknown {
168            annotations: __self_annotations,
169            value_reference: __self_value_reference.ok_or(XmlError::MissingField {
170                name: stringify!(Fmi3Unknown_).to_owned(),
171                field: stringify!(value_reference).to_owned(),
172            })?,
173            dependencies: __self_dependencies,
174            dependencies_kind: __self_dependencies_kind,
175        };
176        ::hard_xml::log_finish_reading!(Fmi3Unknown_);
177        Ok(__res)
178    }
179}
180
181impl Fmi3Unknown {
182    /// Custom implementation of to_writer allowing to specify tag name
183    fn to_writer_with_tag<W: std::io::Write>(
184        &self,
185        writer: &mut ::hard_xml::XmlWriter<W>,
186        tag: &str,
187    ) -> ::hard_xml::XmlResult<()> {
188        let Fmi3Unknown {
189            annotations: __self_annotations,
190            value_reference: __self_value_reference,
191            dependencies: __self_dependencies,
192            dependencies_kind: __self_dependencies_kind,
193        } = self;
194        ::hard_xml::log_start_writing!(Fmi3Unknown);
195        writer.write_element_start(tag)?;
196        ::hard_xml::log_start_writing_field!(Fmi3Unknown, __self_value_reference);
197        let __value = __self_value_reference;
198        writer.write_attribute("valueReference", &format!("{}", __value))?;
199        ::hard_xml::log_finish_writing_field!(Fmi3Unknown, __self_value_reference);
200        ::hard_xml::log_start_writing_field!(Fmi3Unknown, __self_dependencies);
201        if let Some(__value) = __self_dependencies {
202            writer.write_attribute("dependencies", &format!("{}", __value))?;
203        }
204        ::hard_xml::log_finish_writing_field!(Fmi3Unknown, __self_dependencies);
205        ::hard_xml::log_start_writing_field!(Fmi3Unknown, __self_dependencies_kind);
206        if let Some(__value) = __self_dependencies_kind {
207            writer.write_attribute("dependenciesKind", &format!("{}", __value))?;
208        }
209        ::hard_xml::log_finish_writing_field!(Fmi3Unknown, __self_dependencies_kind);
210        if __self_annotations.is_none() {
211            writer.write_element_end_empty()?;
212        } else {
213            writer.write_element_end_open()?;
214            ::hard_xml::log_start_writing_field!(Fmi3Unknown, __self_annotations);
215            if let Some(ele) = __self_annotations {
216                hard_xml::XmlWrite::to_writer(ele, writer)?;
217            }
218            ::hard_xml::log_finish_writing_field!(Fmi3Unknown, __self_annotations);
219            writer.write_element_end_close(tag)?;
220        }
221        ::hard_xml::log_finish_writing!(Fmi3Unknown);
222        Ok(())
223    }
224}
225
226#[derive(PartialEq, Debug, hard_xml::XmlRead)]
227pub enum VariableDependency {
228    #[xml(tag = "Output")]
229    Output(Fmi3Unknown),
230    #[xml(tag = "ContinuousStateDerivative")]
231    ContinuousStateDerivative(Fmi3Unknown),
232    #[xml(tag = "ClockedState")]
233    ClockedState(Fmi3Unknown),
234    #[xml(tag = "InitialUnknown")]
235    InitialUnknown(Fmi3Unknown),
236    #[xml(tag = "EventIndicator")]
237    EventIndicator(Fmi3Unknown),
238}
239
240impl hard_xml::XmlWrite for VariableDependency {
241    fn to_writer<W: std::io::Write>(
242        &self,
243        writer: &mut hard_xml::XmlWriter<W>,
244    ) -> hard_xml::XmlResult<()> {
245        match self {
246            VariableDependency::Output(__inner) => {
247                ::hard_xml::log_start_writing!(VariableDependency::Output);
248                __inner.to_writer_with_tag(writer, "Output")?;
249                ::hard_xml::log_finish_writing!(VariableDependency::Output);
250            }
251            VariableDependency::ContinuousStateDerivative(__inner) => {
252                ::hard_xml::log_start_writing!(VariableDependency::ContinuousStateDerivative);
253                __inner.to_writer_with_tag(writer, "ContinuousStateDerivative")?;
254                ::hard_xml::log_finish_writing!(VariableDependency::ContinuousStateDerivative);
255            }
256            VariableDependency::ClockedState(__inner) => {
257                ::hard_xml::log_start_writing!(VariableDependency::ClockedState);
258                __inner.to_writer_with_tag(writer, "ClockedState")?;
259                ::hard_xml::log_finish_writing!(VariableDependency::ClockedState);
260            }
261            VariableDependency::InitialUnknown(__inner) => {
262                ::hard_xml::log_start_writing!(VariableDependency::InitialUnknown);
263                __inner.to_writer_with_tag(writer, "InitialUnknown")?;
264                ::hard_xml::log_finish_writing!(VariableDependency::InitialUnknown);
265            }
266            VariableDependency::EventIndicator(__inner) => {
267                ::hard_xml::log_start_writing!(VariableDependency::EventIndicator);
268                __inner.to_writer_with_tag(writer, "EventIndicator")?;
269                ::hard_xml::log_finish_writing!(VariableDependency::EventIndicator);
270            }
271        }
272        Ok(())
273    }
274}
275
276#[test]
277fn test_dependencies_kind() {
278    let _ = env_logger::builder()
279        .is_test(true)
280        .format_timestamp(None)
281        .try_init();
282
283    use hard_xml::{XmlRead, XmlWrite};
284    let xml = r#"<Output valueReference="1" dependencies="0 1 2" dependenciesKind="dependent constant fixed"/>"#;
285
286    let var = VariableDependency::from_str(xml).unwrap();
287
288    assert_eq!(
289        var,
290        VariableDependency::Output(Fmi3Unknown {
291            value_reference: 1,
292            dependencies: Some(AttrList(vec![0, 1, 2])),
293            dependencies_kind: Some(AttrList(vec![
294                DependenciesKind::Dependent,
295                DependenciesKind::Constant,
296                DependenciesKind::Fixed
297            ])),
298            ..Default::default()
299        })
300    );
301
302    let xml_out = var.to_string().unwrap();
303    assert_eq!(xml_out, xml);
304}