svd_encoder/
device.rs

1use svd_rs::Peripheral;
2
3use super::{new_node, Config, Element, Encode, EncodeChildren, EncodeError, XMLNode};
4use crate::{
5    config::{DerivableSorting, Sorting},
6    svd::Device,
7};
8
9impl Encode for Device {
10    type Error = EncodeError;
11
12    fn encode_with_config(&self, config: &Config) -> Result<Element, EncodeError> {
13        let mut elem = Element::new("device");
14        if let Some(v) = &self.vendor {
15            elem.children.push(new_node("vendor", v.clone()));
16        }
17        if let Some(v) = &self.vendor_id {
18            elem.children.push(new_node("vendorID", v.clone()));
19        }
20
21        elem.children.push(new_node("name", self.name.clone()));
22
23        if let Some(v) = &self.series {
24            elem.children.push(new_node("series", v.clone()));
25        }
26
27        elem.children
28            .push(new_node("version", self.version.clone()));
29
30        elem.children
31            .push(new_node("description", self.description.clone()));
32
33        if let Some(v) = &self.license_text {
34            elem.children.push(new_node("licenseText", v.clone()));
35        }
36
37        if let Some(v) = &self.cpu {
38            elem.children
39                .push(XMLNode::Element(v.encode_with_config(config)?));
40        }
41
42        if let Some(v) = &self.header_system_filename {
43            elem.children
44                .push(new_node("headerSystemFilename", v.clone()));
45        }
46
47        if let Some(v) = &self.header_definitions_prefix {
48            elem.children
49                .push(new_node("headerDefinitionsPrefix", v.clone()));
50        }
51
52        elem.children.push(new_node(
53            "addressUnitBits",
54            format!("{}", self.address_unit_bits),
55        ));
56
57        elem.children
58            .push(new_node("width", format!("{}", self.width)));
59
60        elem.children.extend(
61            self.default_register_properties
62                .encode_with_config(config)?,
63        );
64
65        let peripherals: Result<Vec<_>, _> =
66            if config.peripheral_sorting == DerivableSorting::Unchanged(None) {
67                self.peripherals
68                    .iter()
69                    .map(|peripheral| peripheral.encode_node_with_config(config))
70                    .collect()
71            } else {
72                sort_derived_peripherals(&self.peripherals, config.peripheral_sorting)
73                    .into_iter()
74                    .map(|peripheral| peripheral.encode_node_with_config(config))
75                    .collect()
76            };
77
78        elem.children.push({
79            let mut e = Element::new("peripherals");
80            e.children = peripherals?;
81            XMLNode::Element(e)
82        });
83
84        elem.attributes
85            .insert(String::from("schemaVersion"), self.schema_version.clone());
86        elem.attributes
87            .insert(String::from("xmlns:xs"), self.xmlns_xs.clone());
88        elem.attributes.insert(
89            String::from("xs:noNamespaceSchemaLocation"),
90            self.no_namespace_schema_location.clone(),
91        );
92
93        Ok(elem)
94    }
95}
96
97fn sort_peripherals(refs: &mut [&Peripheral], sorting: Option<Sorting>) {
98    if let Some(sorting) = sorting {
99        match sorting {
100            Sorting::Offset => refs.sort_by_key(|p| p.base_address),
101            Sorting::OffsetReversed => {
102                refs.sort_by_key(|p| -(p.base_address as i32));
103            }
104            Sorting::Name => refs.sort_by_key(|p| &p.name),
105        }
106    }
107}
108
109fn sort_derived_peripherals(
110    peripherals: &[Peripheral],
111    sorting: DerivableSorting,
112) -> Vec<&Peripheral> {
113    match sorting {
114        DerivableSorting::Unchanged(sorting) => {
115            let mut refs = peripherals.iter().collect::<Vec<_>>();
116            sort_peripherals(&mut refs, sorting);
117            refs
118        }
119        DerivableSorting::DeriveLast(sorting) => {
120            let mut common_refs = peripherals
121                .iter()
122                .filter(|p| p.derived_from.is_none())
123                .collect::<Vec<_>>();
124            let mut derived_refs = peripherals
125                .iter()
126                .filter(|p| p.derived_from.is_some())
127                .collect::<Vec<_>>();
128            sort_peripherals(&mut common_refs, sorting);
129            sort_peripherals(&mut derived_refs, sorting);
130            common_refs.extend(derived_refs);
131            common_refs
132        }
133    }
134}