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}