rust_bitfield_serializer/
types.rs1use std::collections::HashMap;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct BitField {
8 pub name: String,
10 pub bits: usize,
12 pub field_type: FieldType,
14}
15
16impl BitField {
17 pub fn new(name: impl Into<String>, bits: usize, field_type: FieldType) -> Self {
19 Self {
20 name: name.into(),
21 bits,
22 field_type,
23 }
24 }
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum FieldType {
30 U8,
32 U16,
34 U32,
36 U64,
38 Nested(String),
40}
41
42impl FieldType {
43 pub fn default_bit_size(&self) -> Option<usize> {
45 match self {
46 FieldType::U8 => Some(8),
47 FieldType::U16 => Some(16),
48 FieldType::U32 => Some(32),
49 FieldType::U64 => Some(64),
50 FieldType::Nested(_) => None, }
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct BitfieldStruct {
58 pub name: String,
60 pub fields: Vec<BitField>,
62}
63
64impl BitfieldStruct {
65 pub fn new(name: impl Into<String>) -> Self {
67 Self {
68 name: name.into(),
69 fields: Vec::new(),
70 }
71 }
72
73 pub fn add_field(&mut self, name: impl Into<String>, bits: usize, field_type: FieldType) {
75 self.fields.push(BitField::new(name, bits, field_type));
76 }
77
78 pub fn bit_size(&self, structs: &HashMap<String, BitfieldStruct>) -> usize {
80 self.fields
81 .iter()
82 .map(|field| match &field.field_type {
83 FieldType::Nested(struct_name) => {
84 if let Some(nested) = structs.get(struct_name) {
85 nested.bit_size(structs)
86 } else {
87 0 }
89 }
90 _ => field.bits,
91 })
92 .sum()
93 }
94
95 pub fn byte_size(&self, structs: &HashMap<String, BitfieldStruct>) -> usize {
97 self.bit_size(structs).div_ceil(8)
98 }
99
100 pub fn get_field(&self, name: &str) -> Option<&BitField> {
102 self.fields.iter().find(|field| field.name == name)
103 }
104
105 pub fn field_bit_offset(
107 &self,
108 field_name: &str,
109 structs: &HashMap<String, BitfieldStruct>,
110 ) -> Option<usize> {
111 let mut offset = 0;
112 for field in &self.fields {
113 if field.name == field_name {
114 return Some(offset);
115 }
116 offset += match &field.field_type {
117 FieldType::Nested(struct_name) => {
118 if let Some(nested) = structs.get(struct_name) {
119 nested.bit_size(structs)
120 } else {
121 0
122 }
123 }
124 _ => field.bits,
125 };
126 }
127 None
128 }
129}
130
131#[derive(Debug, Clone, PartialEq)]
133pub struct BitfieldValue {
134 pub struct_name: String,
136 pub values: HashMap<String, FieldValue>,
138}
139
140impl BitfieldValue {
141 pub fn new(struct_name: impl Into<String>) -> Self {
143 Self {
144 struct_name: struct_name.into(),
145 values: HashMap::new(),
146 }
147 }
148
149 pub fn set_u8(&mut self, field_name: impl Into<String>, value: u8) {
151 self.values.insert(field_name.into(), FieldValue::U8(value));
152 }
153
154 pub fn set_u16(&mut self, field_name: impl Into<String>, value: u16) {
156 self.values
157 .insert(field_name.into(), FieldValue::U16(value));
158 }
159
160 pub fn set_u32(&mut self, field_name: impl Into<String>, value: u32) {
162 self.values
163 .insert(field_name.into(), FieldValue::U32(value));
164 }
165
166 pub fn set_u64(&mut self, field_name: impl Into<String>, value: u64) {
168 self.values
169 .insert(field_name.into(), FieldValue::U64(value));
170 }
171
172 pub fn set_nested(&mut self, field_name: impl Into<String>, value: BitfieldValue) {
174 self.values
175 .insert(field_name.into(), FieldValue::Nested(Box::new(value)));
176 }
177
178 pub fn get_u8(&self, field_name: &str) -> Option<u8> {
180 match self.values.get(field_name)? {
181 FieldValue::U8(val) => Some(*val),
182 _ => None,
183 }
184 }
185
186 pub fn get_u16(&self, field_name: &str) -> Option<u16> {
188 match self.values.get(field_name)? {
189 FieldValue::U16(val) => Some(*val),
190 _ => None,
191 }
192 }
193
194 pub fn get_u32(&self, field_name: &str) -> Option<u32> {
196 match self.values.get(field_name)? {
197 FieldValue::U32(val) => Some(*val),
198 _ => None,
199 }
200 }
201
202 pub fn get_u64(&self, field_name: &str) -> Option<u64> {
204 match self.values.get(field_name)? {
205 FieldValue::U64(val) => Some(*val),
206 _ => None,
207 }
208 }
209
210 pub fn get_nested(&self, field_name: &str) -> Option<&BitfieldValue> {
212 match self.values.get(field_name)? {
213 FieldValue::Nested(val) => Some(val),
214 _ => None,
215 }
216 }
217
218 pub fn get_nested_mut(&mut self, field_name: &str) -> Option<&mut BitfieldValue> {
220 match self.values.get_mut(field_name)? {
221 FieldValue::Nested(val) => Some(val),
222 _ => None,
223 }
224 }
225}
226
227#[derive(Debug, Clone, PartialEq)]
229pub enum FieldValue {
230 U8(u8),
232 U16(u16),
234 U32(u32),
236 U64(u64),
238 Nested(Box<BitfieldValue>),
240}
241
242impl FieldValue {
243 pub fn to_u64(&self) -> u64 {
245 match self {
246 FieldValue::U8(val) => *val as u64,
247 FieldValue::U16(val) => *val as u64,
248 FieldValue::U32(val) => *val as u64,
249 FieldValue::U64(val) => *val,
250 FieldValue::Nested(_) => 0, }
252 }
253
254 pub fn field_type(&self) -> FieldType {
256 match self {
257 FieldValue::U8(_) => FieldType::U8,
258 FieldValue::U16(_) => FieldType::U16,
259 FieldValue::U32(_) => FieldType::U32,
260 FieldValue::U64(_) => FieldType::U64,
261 FieldValue::Nested(val) => FieldType::Nested(val.struct_name.clone()),
262 }
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269
270 #[test]
271 fn test_bitfield_struct_creation() {
272 let mut bf_struct = BitfieldStruct::new("TestStruct");
273 bf_struct.add_field("field1", 4, FieldType::U8);
274 bf_struct.add_field("field2", 8, FieldType::U16);
275
276 assert_eq!(bf_struct.name, "TestStruct");
277 assert_eq!(bf_struct.fields.len(), 2);
278 assert_eq!(bf_struct.fields[0].name, "field1");
279 assert_eq!(bf_struct.fields[0].bits, 4);
280 }
281
282 #[test]
283 fn test_bitfield_value_operations() {
284 let mut value = BitfieldValue::new("TestStruct");
285 value.set_u8("field1", 42);
286 value.set_u16("field2", 1024);
287
288 assert_eq!(value.get_u8("field1"), Some(42));
289 assert_eq!(value.get_u16("field2"), Some(1024));
290 assert_eq!(value.get_u8("nonexistent"), None);
291 }
292
293 #[test]
294 fn test_nested_structures() {
295 let mut nested = BitfieldValue::new("NestedStruct");
296 nested.set_u8("inner_field", 100);
297
298 let mut parent = BitfieldValue::new("ParentStruct");
299 parent.set_nested("nested", nested);
300
301 let retrieved = parent.get_nested("nested").unwrap();
302 assert_eq!(retrieved.get_u8("inner_field"), Some(100));
303 }
304
305 #[test]
306 fn test_bit_size_calculation() {
307 let mut structs = HashMap::new();
308
309 let mut bf_struct = BitfieldStruct::new("TestStruct");
310 bf_struct.add_field("field1", 4, FieldType::U8);
311 bf_struct.add_field("field2", 12, FieldType::U16);
312
313 structs.insert("TestStruct".to_string(), bf_struct.clone());
314
315 assert_eq!(bf_struct.bit_size(&structs), 16);
316 assert_eq!(bf_struct.byte_size(&structs), 2);
317 }
318
319 #[test]
320 fn test_field_offset_calculation() {
321 let mut structs = HashMap::new();
322
323 let mut bf_struct = BitfieldStruct::new("TestStruct");
324 bf_struct.add_field("field1", 4, FieldType::U8);
325 bf_struct.add_field("field2", 8, FieldType::U16);
326 bf_struct.add_field("field3", 4, FieldType::U8);
327
328 structs.insert("TestStruct".to_string(), bf_struct.clone());
329
330 assert_eq!(bf_struct.field_bit_offset("field1", &structs), Some(0));
331 assert_eq!(bf_struct.field_bit_offset("field2", &structs), Some(4));
332 assert_eq!(bf_struct.field_bit_offset("field3", &structs), Some(12));
333 assert_eq!(bf_struct.field_bit_offset("nonexistent", &structs), None);
334 }
335}