1if_alloc! {
11 use crate::alloc::{string::String, fmt::format};
12}
13
14use bitfield_struct::bitfield;
15
16use crate::conversion::Conversion;
17
18pub trait IsDataUnit {}
20
21#[bitfield(u64, order = Msb, conversion = false)]
36#[derive(PartialEq, Eq, PartialOrd, Ord)]
37pub struct Data {
38 #[bits(8)]
39 byte_0_bits: u8,
40 #[bits(8)]
41 byte_1_bits: u8,
42 #[bits(8)]
43 byte_2_bits: u8,
44 #[bits(8)]
45 byte_3_bits: u8,
46 #[bits(8)]
47 byte_4_bits: u8,
48 #[bits(8)]
49 byte_5_bits: u8,
50 #[bits(8)]
51 byte_6_bits: u8,
52 #[bits(8)]
53 byte_7_bits: u8,
54}
55
56#[bitfield(u64, order = Msb, conversion = false)]
75#[derive(PartialEq, Eq, PartialOrd, Ord)]
76pub struct Name {
77 #[bits(1)]
78 arbitrary_address_bits: bool,
79 #[bits(3)]
80 industry_group_bits: u8,
81 #[bits(4)]
82 vehicle_system_instance_bits: u8,
83 #[bits(7)]
84 vehicle_system_bits: u8,
85 #[bits(1)]
86 reserved_bits: bool,
87 #[bits(8)]
88 function_bits: u8,
89 #[bits(5)]
90 function_instance_bits: u8,
91 #[bits(3)]
92 ecu_instance_bits: u8,
93 #[bits(11)]
94 manufacturer_code_bits: u16,
95 #[bits(21)]
96 identity_number_bits: u32,
97}
98
99impl IsDataUnit for Data {}
100impl IsDataUnit for Name {}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
104pub struct Pdu<U: IsDataUnit>(pub(crate) U);
105
106impl Conversion<u64> for Pdu<Data> {
107 type Error = anyhow::Error;
108
109 fn from_bits(bits: u64) -> Self {
111 Self(Data(bits))
112 }
113
114 fn from_hex(hex_str: &str) -> Self {
116 let bits = u64::from_str_radix(hex_str, 16).unwrap_or_default();
117
118 Self(Data(bits))
119 }
120
121 fn try_from_bits(bits: u64) -> Result<Self, Self::Error> {
125 Ok(Self(Data(bits)))
126 }
127
128 fn try_from_hex(hex_str: &str) -> Result<Self, Self::Error> {
132 let bits = u64::from_str_radix(hex_str, 16).map_err(anyhow::Error::msg)?;
133
134 Ok(Self(Data(bits)))
135 }
136
137 fn into_bits(self) -> u64 {
139 self.0 .0
140 }
141
142 #[cfg(feature = "alloc")]
146 fn into_hex(self) -> String {
147 format(format_args!("{:016X}", self.0 .0))
148 }
149}
150
151impl Pdu<Data> {
152 #[must_use]
154 pub const fn byte_0(self) -> u8 {
155 self.0.byte_0_bits()
156 }
157
158 #[must_use]
160 pub const fn byte_1(self) -> u8 {
161 self.0.byte_1_bits()
162 }
163
164 #[must_use]
166 pub const fn byte_2(self) -> u8 {
167 self.0.byte_2_bits()
168 }
169
170 #[must_use]
172 pub const fn byte_3(self) -> u8 {
173 self.0.byte_3_bits()
174 }
175
176 #[must_use]
178 pub const fn byte_4(self) -> u8 {
179 self.0.byte_4_bits()
180 }
181
182 #[must_use]
184 pub const fn byte_5(self) -> u8 {
185 self.0.byte_5_bits()
186 }
187
188 #[must_use]
190 pub const fn byte_6(self) -> u8 {
191 self.0.byte_6_bits()
192 }
193
194 #[must_use]
196 pub const fn byte_7(self) -> u8 {
197 self.0.byte_7_bits()
198 }
199
200 #[must_use]
202 pub const fn to_le_bytes(&self) -> [u8; 8] {
203 self.0 .0.to_le_bytes()
204 }
205
206 #[must_use]
208 pub const fn to_be_bytes(&self) -> [u8; 8] {
209 self.0 .0.to_be_bytes()
210 }
211
212 #[must_use]
214 pub const fn to_ne_bytes(&self) -> [u8; 8] {
215 self.0 .0.to_ne_bytes()
216 }
217
218 #[must_use]
220 pub const fn to_le(&self) -> Self {
221 Self(Data(self.0 .0.to_le()))
222 }
223
224 #[must_use]
226 pub const fn to_be(&self) -> Self {
227 Self(Data(self.0 .0.to_be()))
228 }
229}
230
231impl Conversion<u64> for Pdu<Name> {
232 type Error = anyhow::Error;
233
234 fn from_bits(bits: u64) -> Self {
236 Self(Name(bits))
237 }
238
239 fn from_hex(hex_str: &str) -> Self {
241 let bits = u64::from_str_radix(hex_str, 16).unwrap_or_default();
242
243 Self(Name(bits))
244 }
245
246 fn try_from_bits(bits: u64) -> Result<Self, Self::Error> {
250 Ok(Self(Name(bits)))
251 }
252
253 fn try_from_hex(hex_str: &str) -> Result<Self, Self::Error> {
258 let bits = u64::from_str_radix(hex_str, 16).map_err(anyhow::Error::msg)?;
259
260 Ok(Self(Name(bits)))
261 }
262
263 fn into_bits(self) -> u64 {
265 self.0 .0
266 }
267
268 #[cfg(feature = "alloc")]
272 fn into_hex(self) -> String {
273 format(format_args!("{:016X}", self.0 .0))
274 }
275}
276
277impl Pdu<Name> {
278 #[must_use]
280 pub const fn arbitrary_address(&self) -> bool {
281 self.0.arbitrary_address_bits()
282 }
283
284 #[must_use]
287 pub const fn industry_group(&self) -> u8 {
288 self.0.industry_group_bits()
289 }
290
291 #[must_use]
294 pub const fn vehicle_system_instance(&self) -> u8 {
295 self.0.vehicle_system_instance_bits()
296 }
297
298 #[must_use]
301 pub const fn vehicle_system(&self) -> u8 {
302 self.0.vehicle_system_bits()
303 }
304
305 #[must_use]
307 pub const fn reserved(&self) -> bool {
308 self.0.reserved_bits()
309 }
310
311 #[must_use]
314 pub const fn function(&self) -> u8 {
315 self.0.function_bits()
316 }
317
318 #[must_use]
320 pub const fn function_instance(&self) -> u8 {
321 self.0.function_instance_bits()
322 }
323
324 #[must_use]
327 pub const fn ecu_instance(&self) -> u8 {
328 self.0.ecu_instance_bits()
329 }
330
331 #[must_use]
333 pub const fn manufacturer_code(&self) -> u16 {
334 self.0.manufacturer_code_bits()
335 }
336
337 #[must_use]
340 pub const fn identity_number(&self) -> u32 {
341 self.0.identity_number_bits()
342 }
343}
344
345#[cfg(test)]
346mod data_tests {
347 use super::*;
348
349 #[test]
350 fn test_data_bitfield() -> Result<(), anyhow::Error> {
351 let data_a = Pdu::<Data>::from_hex("FFFF82DF1AFFFFFF");
352 let be_bytes_a: [u8; 8] = [0xFF, 0xFF, 0x82, 0xDF, 0x1A, 0xFF, 0xFF, 0xFF];
353 let le_bytes_a: [u8; 8] = [0xFF, 0xFF, 0xFF, 0x1A, 0xDF, 0x82, 0xFF, 0xFF];
354
355 assert_eq!(be_bytes_a, data_a.to_be_bytes());
356 assert_eq!(le_bytes_a, data_a.to_le_bytes());
357
358 assert_eq!(18446606493475143679, data_a.into_bits());
359
360 assert_eq!(Pdu::<Data>(Data(18446743089616977919)), data_a.to_be());
361 assert_eq!(Pdu::<Data>(Data(18446606493475143679)), data_a.to_le());
362
363 Ok(())
364 }
365
366 #[test]
367 fn test_name_bitfield() {
368 let name_a = Name::new()
369 .with_arbitrary_address_bits(true)
370 .with_industry_group_bits(0)
371 .with_vehicle_system_instance_bits(0x5)
372 .with_vehicle_system_bits(0x6)
373 .with_reserved_bits(false)
374 .with_function_bits(0x5)
375 .with_function_instance_bits(0x2)
376 .with_ecu_instance_bits(0x1)
377 .with_manufacturer_code_bits(0x122)
378 .with_identity_number_bits(0xB0309);
379
380 let pdu_name = Pdu::<Name>(name_a);
381
382 let bytes_a: [u8; 8] = [0x09, 0x03, 0x4B, 0x24, 0x11, 0x05, 0x0C, 0x85];
383 let name_a_bytes = pdu_name.into_bits().to_le_bytes();
384
385 assert_eq!(bytes_a, name_a_bytes);
386 }
387}