svd_encoder/
peripheral.rs1use svd_rs::RegisterCluster;
2
3use super::{
4 new_node, Config, Element, ElementMerge, Encode, EncodeChildren, EncodeError, XMLNode,
5};
6
7use crate::{
8 config::{change_case, format_number, DerivableSorting, RcSorting, Sorting},
9 svd::{Peripheral, PeripheralInfo},
10};
11
12impl Encode for Peripheral {
13 type Error = EncodeError;
14
15 fn encode_with_config(&self, config: &Config) -> Result<Element, EncodeError> {
16 match self {
17 Self::Single(info) => info.encode_with_config(config),
18 Self::Array(info, array_info) => {
19 let mut base = Element::new("peripheral");
20 base.merge(&array_info.encode_with_config(config)?);
21 base.merge(&info.encode_with_config(config)?);
22 Ok(base)
23 }
24 }
25 }
26}
27
28impl Encode for PeripheralInfo {
29 type Error = EncodeError;
30
31 fn encode_with_config(&self, config: &Config) -> Result<Element, EncodeError> {
32 let mut elem = Element::new("peripheral");
33 elem.children.push(new_node(
34 "name",
35 change_case(&self.name, config.peripheral_name),
36 ));
37
38 if let Some(v) = &self.display_name {
39 elem.children.push(new_node("displayName", v.to_string()));
40 }
41
42 if let Some(v) = &self.version {
43 elem.children.push(new_node("version", v.to_string()));
44 }
45
46 if let Some(v) = &self.description {
47 elem.children.push(new_node("description", v.to_string()));
48 }
49
50 if let Some(v) = &self.alternate_peripheral {
51 elem.children.push(new_node(
52 "alternatePeripheral",
53 change_case(v, config.peripheral_name),
54 ));
55 }
56
57 if let Some(v) = &self.group_name {
58 elem.children.push(new_node("groupName", v.to_string()));
59 }
60
61 if let Some(v) = &self.prepend_to_name {
62 elem.children.push(new_node(
63 "prependToName",
64 change_case(v, config.peripheral_name),
65 ));
66 }
67
68 if let Some(v) = &self.append_to_name {
69 elem.children.push(new_node(
70 "appendToName",
71 change_case(v, config.peripheral_name),
72 ));
73 }
74
75 if let Some(v) = &self.header_struct_name {
76 elem.children.push(new_node(
77 "headerStructName",
78 change_case(v, config.peripheral_name),
79 ));
80 }
81
82 elem.children.push(new_node(
83 "baseAddress",
84 format_number(self.base_address, config.peripheral_base_address),
85 ));
86
87 elem.children.extend(
88 self.default_register_properties
89 .encode_with_config(config)?,
90 );
91
92 if let Some(v) = &self.address_block {
93 for ab in v {
94 elem.children.push(ab.encode_node_with_config(config)?);
95 }
96 }
97
98 let interrupts: Result<Vec<_>, _> = self
99 .interrupt
100 .iter()
101 .map(|interrupt| interrupt.encode_node_with_config(config))
102 .collect();
103
104 elem.children.append(&mut interrupts?);
105
106 if let Some(v) = &self.registers {
107 let children: Result<Vec<_>, _> = match config.register_cluster_sorting {
108 RcSorting::Unchanged(DerivableSorting::Unchanged(None)) => v
109 .iter()
110 .map(|e| e.encode_node_with_config(config))
111 .collect(),
112 RcSorting::Unchanged(sorting) => sort_derived_register_cluster(v, sorting)
113 .into_iter()
114 .map(|e| e.encode_node_with_config(config))
115 .collect(),
116 RcSorting::RegistersFirst(sorting) => rc_sort(v, sorting, true)
117 .map(|e| e.encode_node_with_config(config))
118 .collect(),
119 RcSorting::ClustersFirst(sorting) => rc_sort(v, sorting, false)
120 .map(|e| e.encode_node_with_config(config))
121 .collect(),
122 };
123
124 elem.children.push({
125 let mut e = Element::new("registers");
126 e.children = children?;
127 XMLNode::Element(e)
128 });
129 }
130
131 if let Some(v) = &self.derived_from {
132 elem.attributes.insert(
133 String::from("derivedFrom"),
134 change_case(v, config.peripheral_name),
135 );
136 }
137
138 Ok(elem)
139 }
140}
141
142fn sort_register_cluster(refs: &mut [&RegisterCluster], sorting: Option<Sorting>) {
143 if let Some(sorting) = sorting {
144 match sorting {
145 Sorting::Offset => refs.sort_by_key(|r| r.address_offset()),
146 Sorting::OffsetReversed => {
147 refs.sort_by_key(|r| -(r.address_offset() as i32));
148 }
149 Sorting::Name => refs.sort_by_key(|r| r.name()),
150 }
151 }
152}
153
154fn sort_derived_register_cluster<'a>(
155 rcs: impl IntoIterator<Item = &'a RegisterCluster>,
156 sorting: DerivableSorting,
157) -> Vec<&'a RegisterCluster> {
158 match sorting {
159 DerivableSorting::Unchanged(sorting) => {
160 let mut refs = rcs.into_iter().collect::<Vec<_>>();
161 sort_register_cluster(&mut refs, sorting);
162 refs
163 }
164 DerivableSorting::DeriveLast(sorting) => {
165 let mut common_refs = Vec::new();
166 let mut derived_refs = Vec::new();
167 for rc in rcs {
168 if rc.derived_from().is_some() {
169 derived_refs.push(rc);
170 } else {
171 common_refs.push(rc);
172 }
173 }
174 sort_register_cluster(&mut common_refs, sorting);
175 sort_register_cluster(&mut derived_refs, sorting);
176 common_refs.extend(derived_refs);
177 common_refs
178 }
179 }
180}
181
182fn rc_sort(
183 v: &[RegisterCluster],
184 sorting: DerivableSorting,
185 register_first: bool,
186) -> impl Iterator<Item = &RegisterCluster> {
187 let reg_refs = v
188 .iter()
189 .filter(|rc| matches!(rc, RegisterCluster::Register(_)))
190 .collect::<Vec<_>>();
191 let reg_refs = sort_derived_register_cluster(reg_refs, sorting);
192
193 let c_refs = v
194 .iter()
195 .filter(|rc| matches!(rc, RegisterCluster::Cluster(_)))
196 .collect::<Vec<_>>();
197 let c_refs = sort_derived_register_cluster(c_refs, sorting);
198 if register_first {
199 reg_refs.into_iter().chain(c_refs)
200 } else {
201 c_refs.into_iter().chain(reg_refs)
202 }
203}