1use svd_rs::Field;
2
3use super::{
4 new_node, Config, Element, ElementMerge, Encode, EncodeChildren, EncodeError, XMLNode,
5};
6
7use crate::{
8 config::{change_case, format_number, DerivableSorting, Sorting},
9 svd::{Register, RegisterInfo},
10};
11
12impl Encode for Register {
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("register");
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 RegisterInfo {
29 type Error = EncodeError;
30
31 fn encode_with_config(&self, config: &Config) -> Result<Element, EncodeError> {
32 let mut elem = Element::new("register");
33 elem.children.push(new_node(
34 "name",
35 change_case(&self.name, config.register_name),
36 ));
37
38 if let Some(v) = &self.display_name {
39 elem.children.push(new_node("displayName", v.clone()));
40 }
41
42 if let Some(v) = &self.description {
43 elem.children.push(new_node("description", v.clone()));
44 }
45
46 if let Some(v) = &self.alternate_group {
47 elem.children
48 .push(new_node("alternateGroup", v.to_string()));
49 }
50
51 if let Some(v) = &self.alternate_register {
52 elem.children.push(new_node(
53 "alternateRegister",
54 change_case(v, config.register_name),
55 ));
56 }
57
58 elem.children.push(new_node(
59 "addressOffset",
60 format_number(self.address_offset, config.register_address_offset),
61 ));
62
63 elem.children
64 .extend(self.properties.encode_with_config(config)?);
65
66 if let Some(v) = &self.datatype {
67 elem.children.push(v.encode_node_with_config(config)?);
68 }
69
70 if let Some(v) = &self.modified_write_values {
71 elem.children.push(v.encode_node_with_config(config)?);
72 }
73
74 if let Some(v) = &self.write_constraint {
75 elem.children.push(v.encode_node()?);
76 }
77
78 if let Some(v) = &self.read_action {
79 elem.children.push(v.encode_node()?);
80 }
81
82 if let Some(v) = &self.fields {
83 let children: Result<Vec<_>, _> =
84 if config.field_sorting == DerivableSorting::Unchanged(None) {
85 v.iter()
86 .map(|field| field.encode_node_with_config(config))
87 .collect()
88 } else {
89 sort_derived_fields(v, config.field_sorting)
90 .into_iter()
91 .map(|field| field.encode_node_with_config(config))
92 .collect()
93 };
94
95 let children = children?;
96 if !children.is_empty() {
97 let mut fields = Element::new("fields");
98 fields.children = children;
99 elem.children.push(XMLNode::Element(fields));
100 }
101 }
102
103 if let Some(v) = &self.derived_from {
104 elem.attributes.insert(
105 String::from("derivedFrom"),
106 change_case(v, config.register_name),
107 );
108 }
109
110 Ok(elem)
111 }
112}
113
114fn sort_fields(refs: &mut [&Field], sorting: Option<Sorting>) {
115 if let Some(sorting) = sorting {
116 match sorting {
117 Sorting::Offset => refs.sort_by_key(|f| f.bit_offset()),
118 Sorting::OffsetReversed => {
119 refs.sort_by_key(|f| -(f.bit_offset() as i32));
120 }
121 Sorting::Name => refs.sort_by_key(|f| &f.name),
122 }
123 }
124}
125
126fn sort_derived_fields(v: &[Field], sorting: DerivableSorting) -> Vec<&Field> {
127 match sorting {
128 DerivableSorting::Unchanged(sorting) => {
129 let mut refs = v.iter().collect::<Vec<_>>();
130 sort_fields(&mut refs, sorting);
131 refs
132 }
133 DerivableSorting::DeriveLast(sorting) => {
134 let mut common_refs = Vec::with_capacity(v.len());
135 let mut derived_refs = Vec::new();
136 for f in v.iter() {
137 if f.derived_from.is_some() {
138 derived_refs.push(f);
139 } else {
140 let mut derived = false;
141 for ev in &f.enumerated_values {
142 if ev.derived_from.is_some() {
143 derived_refs.push(f);
144 derived = true;
145 break;
146 }
147 }
148 if !derived {
149 common_refs.push(f);
150 }
151 }
152 }
153 sort_fields(&mut common_refs, sorting);
154 sort_fields(&mut derived_refs, sorting);
155 common_refs.extend(derived_refs);
156
157 common_refs
158 }
159 }
160}