1use std::fmt;
7use std::net::{Ipv4Addr, Ipv6Addr};
8use thiserror::Error;
9
10#[derive(Debug, Error, Clone, PartialEq, Eq)]
12pub enum FieldError {
13 #[error("buffer too short: need {need} bytes at offset {offset}, have {have}")]
14 BufferTooShort {
15 offset: usize,
16 need: usize,
17 have: usize,
18 },
19
20 #[error("invalid MAC address format: {0}")]
21 InvalidMac(String),
22
23 #[error("invalid IP address format: {0}")]
24 InvalidIp(String),
25
26 #[error("field type mismatch: expected {expected}, got {got}")]
27 TypeMismatch {
28 expected: &'static str,
29 got: &'static str,
30 },
31
32 #[error("field not found: {0}")]
33 FieldNotFound(String),
34
35 #[error("invalid field value: {0}")]
36 InvalidValue(String),
37}
38
39#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
41pub struct MacAddress(pub [u8; 6]);
42
43impl MacAddress {
44 pub const ZERO: Self = Self([0x00; 6]);
45 pub const BROADCAST: Self = Self([0xff; 6]);
46 pub const IPV4_MULTICAST_PREFIX: [u8; 3] = [0x01, 0x00, 0x5e];
48 pub const IPV6_MULTICAST_PREFIX: [u8; 2] = [0x33, 0x33];
50
51 #[inline]
52 #[must_use]
53 pub const fn new(bytes: [u8; 6]) -> Self {
54 Self(bytes)
55 }
56
57 #[inline]
58 #[must_use]
59 pub const fn as_bytes(&self) -> &[u8; 6] {
60 &self.0
61 }
62
63 #[inline]
64 #[must_use]
65 pub const fn to_bytes(self) -> [u8; 6] {
66 self.0
67 }
68
69 #[inline]
70 #[must_use]
71 pub fn is_broadcast(&self) -> bool {
72 self.0 == [0xff; 6]
73 }
74
75 #[inline]
76 #[must_use]
77 pub fn is_multicast(&self) -> bool {
78 self.0[0] & 0x01 != 0
79 }
80
81 #[inline]
82 #[must_use]
83 pub fn is_unicast(&self) -> bool {
84 !self.is_multicast()
85 }
86
87 #[inline]
88 #[must_use]
89 pub fn is_local(&self) -> bool {
90 self.0[0] & 0x02 != 0
91 }
92
93 #[inline]
94 #[must_use]
95 pub fn is_zero(&self) -> bool {
96 self.0 == [0x00; 6]
97 }
98
99 #[inline]
101 #[must_use]
102 pub fn is_ipv4_multicast(&self) -> bool {
103 self.0[0] == 0x01 && self.0[1] == 0x00 && self.0[2] == 0x5e
104 }
105
106 #[inline]
108 #[must_use]
109 pub fn is_ipv6_multicast(&self) -> bool {
110 self.0[0] == 0x33 && self.0[1] == 0x33
111 }
112
113 #[must_use]
115 pub fn from_ipv4_multicast(ip: Ipv4Addr) -> Self {
116 let octets = ip.octets();
117 Self([0x01, 0x00, 0x5e, octets[1] & 0x7f, octets[2], octets[3]])
118 }
119
120 #[must_use]
122 pub fn from_ipv6_multicast(ip: Ipv6Addr) -> Self {
123 let octets = ip.octets();
124 Self([0x33, 0x33, octets[12], octets[13], octets[14], octets[15]])
125 }
126
127 pub fn parse(s: &str) -> Result<Self, FieldError> {
129 let s = s.trim();
130 let parts: Vec<&str> = if s.contains(':') {
131 s.split(':').collect()
132 } else if s.contains('-') {
133 s.split('-').collect()
134 } else if s.len() == 12 {
135 return Self::parse_bare_hex(s);
137 } else {
138 return Err(FieldError::InvalidMac(s.to_string()));
139 };
140
141 if parts.len() != 6 {
142 return Err(FieldError::InvalidMac(s.to_string()));
143 }
144
145 let mut bytes = [0u8; 6];
146 for (i, part) in parts.iter().enumerate() {
147 bytes[i] =
148 u8::from_str_radix(part, 16).map_err(|_| FieldError::InvalidMac(s.to_string()))?;
149 }
150 Ok(Self(bytes))
151 }
152
153 fn parse_bare_hex(s: &str) -> Result<Self, FieldError> {
154 if s.len() != 12 {
155 return Err(FieldError::InvalidMac(s.to_string()));
156 }
157 let mut bytes = [0u8; 6];
158 for i in 0..6 {
159 bytes[i] = u8::from_str_radix(&s[i * 2..i * 2 + 2], 16)
160 .map_err(|_| FieldError::InvalidMac(s.to_string()))?;
161 }
162 Ok(Self(bytes))
163 }
164
165 #[inline]
166 pub fn read_from(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
167 <Self as Field>::read(buf, offset)
168 }
169
170 #[inline]
171 pub fn write_to(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
172 <Self as Field>::write(self, buf, offset)
173 }
174}
175
176impl fmt::Debug for MacAddress {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 write!(f, "MacAddress({self})")
179 }
180}
181
182impl fmt::Display for MacAddress {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 write!(
185 f,
186 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
187 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
188 )
189 }
190}
191
192impl From<[u8; 6]> for MacAddress {
193 fn from(bytes: [u8; 6]) -> Self {
194 Self(bytes)
195 }
196}
197
198impl From<MacAddress> for [u8; 6] {
199 fn from(mac: MacAddress) -> Self {
200 mac.0
201 }
202}
203
204impl std::str::FromStr for MacAddress {
205 type Err = FieldError;
206 fn from_str(s: &str) -> Result<Self, Self::Err> {
207 Self::parse(s)
208 }
209}
210
211pub trait Field: Sized {
213 const SIZE: Option<usize>;
215
216 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError>;
218
219 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError>;
221}
222
223impl Field for u8 {
228 const SIZE: Option<usize> = Some(1);
229
230 #[inline]
231 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
232 buf.get(offset).copied().ok_or(FieldError::BufferTooShort {
233 offset,
234 need: 1,
235 have: buf.len(),
236 })
237 }
238
239 #[inline]
240 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
241 let len = buf.len();
242 *buf.get_mut(offset).ok_or(FieldError::BufferTooShort {
243 offset,
244 need: 1,
245 have: len,
246 })? = *self;
247 Ok(())
248 }
249}
250
251impl Field for u16 {
252 const SIZE: Option<usize> = Some(2);
253
254 #[inline]
255 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
256 if buf.len() < offset + 2 {
257 return Err(FieldError::BufferTooShort {
258 offset,
259 need: 2,
260 have: buf.len(),
261 });
262 }
263 Ok(u16::from_be_bytes([buf[offset], buf[offset + 1]]))
264 }
265
266 #[inline]
267 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
268 if buf.len() < offset + 2 {
269 return Err(FieldError::BufferTooShort {
270 offset,
271 need: 2,
272 have: buf.len(),
273 });
274 }
275 let bytes = self.to_be_bytes();
276 buf[offset] = bytes[0];
277 buf[offset + 1] = bytes[1];
278 Ok(())
279 }
280}
281
282impl Field for u32 {
283 const SIZE: Option<usize> = Some(4);
284
285 #[inline]
286 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
287 if buf.len() < offset + 4 {
288 return Err(FieldError::BufferTooShort {
289 offset,
290 need: 4,
291 have: buf.len(),
292 });
293 }
294 Ok(u32::from_be_bytes([
295 buf[offset],
296 buf[offset + 1],
297 buf[offset + 2],
298 buf[offset + 3],
299 ]))
300 }
301
302 #[inline]
303 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
304 if buf.len() < offset + 4 {
305 return Err(FieldError::BufferTooShort {
306 offset,
307 need: 4,
308 have: buf.len(),
309 });
310 }
311 buf[offset..offset + 4].copy_from_slice(&self.to_be_bytes());
312 Ok(())
313 }
314}
315
316impl Field for u64 {
317 const SIZE: Option<usize> = Some(8);
318
319 #[inline]
320 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
321 if buf.len() < offset + 8 {
322 return Err(FieldError::BufferTooShort {
323 offset,
324 need: 8,
325 have: buf.len(),
326 });
327 }
328 let mut bytes = [0u8; 8];
329 bytes.copy_from_slice(&buf[offset..offset + 8]);
330 Ok(u64::from_be_bytes(bytes))
331 }
332
333 #[inline]
334 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
335 if buf.len() < offset + 8 {
336 return Err(FieldError::BufferTooShort {
337 offset,
338 need: 8,
339 have: buf.len(),
340 });
341 }
342 buf[offset..offset + 8].copy_from_slice(&self.to_be_bytes());
343 Ok(())
344 }
345}
346
347impl Field for MacAddress {
348 const SIZE: Option<usize> = Some(6);
349
350 #[inline]
351 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
352 if buf.len() < offset + 6 {
353 return Err(FieldError::BufferTooShort {
354 offset,
355 need: 6,
356 have: buf.len(),
357 });
358 }
359 Ok(Self([
360 buf[offset],
361 buf[offset + 1],
362 buf[offset + 2],
363 buf[offset + 3],
364 buf[offset + 4],
365 buf[offset + 5],
366 ]))
367 }
368
369 #[inline]
370 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
371 if buf.len() < offset + 6 {
372 return Err(FieldError::BufferTooShort {
373 offset,
374 need: 6,
375 have: buf.len(),
376 });
377 }
378 buf[offset..offset + 6].copy_from_slice(&self.0);
379 Ok(())
380 }
381}
382
383impl Field for Ipv4Addr {
384 const SIZE: Option<usize> = Some(4);
385
386 #[inline]
387 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
388 if buf.len() < offset + 4 {
389 return Err(FieldError::BufferTooShort {
390 offset,
391 need: 4,
392 have: buf.len(),
393 });
394 }
395 Ok(Ipv4Addr::new(
396 buf[offset],
397 buf[offset + 1],
398 buf[offset + 2],
399 buf[offset + 3],
400 ))
401 }
402
403 #[inline]
404 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
405 if buf.len() < offset + 4 {
406 return Err(FieldError::BufferTooShort {
407 offset,
408 need: 4,
409 have: buf.len(),
410 });
411 }
412 buf[offset..offset + 4].copy_from_slice(&self.octets());
413 Ok(())
414 }
415}
416
417impl Field for Ipv6Addr {
418 const SIZE: Option<usize> = Some(16);
419
420 #[inline]
421 fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
422 if buf.len() < offset + 16 {
423 return Err(FieldError::BufferTooShort {
424 offset,
425 need: 16,
426 have: buf.len(),
427 });
428 }
429 let mut arr = [0u8; 16];
430 arr.copy_from_slice(&buf[offset..offset + 16]);
431 Ok(Ipv6Addr::from(arr))
432 }
433
434 #[inline]
435 fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
436 if buf.len() < offset + 16 {
437 return Err(FieldError::BufferTooShort {
438 offset,
439 need: 16,
440 have: buf.len(),
441 });
442 }
443 buf[offset..offset + 16].copy_from_slice(&self.octets());
444 Ok(())
445 }
446}
447
448#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
454pub struct BytesField(pub Vec<u8>);
455
456impl BytesField {
457 #[must_use]
458 pub fn new(data: Vec<u8>) -> Self {
459 Self(data)
460 }
461 #[must_use]
462 pub fn from_slice(data: &[u8]) -> Self {
463 Self(data.to_vec())
464 }
465 #[must_use]
466 pub fn as_bytes(&self) -> &[u8] {
467 &self.0
468 }
469 #[must_use]
470 pub fn len(&self) -> usize {
471 self.0.len()
472 }
473 #[must_use]
474 pub fn is_empty(&self) -> bool {
475 self.0.is_empty()
476 }
477
478 pub fn read_with_len(buf: &[u8], offset: usize, len: usize) -> Result<Self, FieldError> {
479 if buf.len() < offset + len {
480 return Err(FieldError::BufferTooShort {
481 offset,
482 need: len,
483 have: buf.len(),
484 });
485 }
486 Ok(Self(buf[offset..offset + len].to_vec()))
487 }
488
489 pub fn write_to(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
490 if buf.len() < offset + self.0.len() {
491 return Err(FieldError::BufferTooShort {
492 offset,
493 need: self.0.len(),
494 have: buf.len(),
495 });
496 }
497 buf[offset..offset + self.0.len()].copy_from_slice(&self.0);
498 Ok(())
499 }
500}
501
502impl From<Vec<u8>> for BytesField {
503 fn from(v: Vec<u8>) -> Self {
504 Self(v)
505 }
506}
507
508impl From<&[u8]> for BytesField {
509 fn from(s: &[u8]) -> Self {
510 Self(s.to_vec())
511 }
512}
513
514#[derive(Debug, Clone, Copy)]
520pub struct FieldDesc {
521 pub name: &'static str,
522 pub offset: usize,
523 pub size: usize,
524 pub field_type: FieldType,
525}
526
527#[derive(Debug, Clone, Copy, PartialEq, Eq)]
529pub enum FieldType {
530 U8,
531 U16,
532 U32,
533 U64,
534 I8,
535 I16,
536 I32,
537 I64,
538 LEU16,
539 LEU32,
540 LEU64,
541 U24,
542 LEU24,
543 Bool,
544 Mac,
545 Ipv4,
546 Ipv6,
547 Bytes,
548 Str,
549 DnsName,
550}
551
552impl FieldType {
553 #[must_use]
554 pub const fn name(&self) -> &'static str {
555 match self {
556 Self::U8 => "u8",
557 Self::U16 => "u16",
558 Self::U32 => "u32",
559 Self::U64 => "u64",
560 Self::I8 => "i8",
561 Self::I16 => "i16",
562 Self::I32 => "i32",
563 Self::I64 => "i64",
564 Self::LEU16 => "le_u16",
565 Self::LEU32 => "le_u32",
566 Self::LEU64 => "le_u64",
567 Self::U24 => "u24",
568 Self::LEU24 => "le_u24",
569 Self::Bool => "bool",
570 Self::Mac => "MAC",
571 Self::Ipv4 => "IPv4",
572 Self::Ipv6 => "IPv6",
573 Self::Bytes => "Bytes",
574 Self::Str => "Str",
575 Self::DnsName => "DnsName",
576 }
577 }
578
579 #[must_use]
580 pub const fn size(&self) -> Option<usize> {
581 match self {
582 Self::U8 | Self::I8 | Self::Bool => Some(1),
583 Self::U16 | Self::I16 | Self::LEU16 => Some(2),
584 Self::U24 | Self::LEU24 => Some(3),
585 Self::U32 | Self::I32 | Self::LEU32 => Some(4),
586 Self::U64 | Self::I64 | Self::LEU64 => Some(8),
587 Self::Mac => Some(6),
588 Self::Ipv4 => Some(4),
589 Self::Ipv6 => Some(16),
590 Self::Bytes | Self::Str | Self::DnsName => None,
591 }
592 }
593}
594
595impl FieldDesc {
596 #[must_use]
597 pub const fn new(
598 name: &'static str,
599 offset: usize,
600 size: usize,
601 field_type: FieldType,
602 ) -> Self {
603 Self {
604 name,
605 offset,
606 size,
607 field_type,
608 }
609 }
610
611 #[inline]
612 #[must_use]
613 pub const fn with_offset(&self, base: usize) -> Self {
614 Self {
615 name: self.name,
616 offset: base + self.offset,
617 size: self.size,
618 field_type: self.field_type,
619 }
620 }
621}
622
623#[derive(Debug, Clone, PartialEq)]
625pub enum FieldValue {
626 U8(u8),
627 U16(u16),
628 U32(u32),
629 U64(u64),
630 I8(i8),
631 I16(i16),
632 I32(i32),
633 I64(i64),
634 Bool(bool),
635 Mac(MacAddress),
636 Ipv4(Ipv4Addr),
637 Ipv6(Ipv6Addr),
638 Bytes(Vec<u8>),
639 Str(String),
640 List(Vec<FieldValue>),
641}
642
643impl FieldValue {
644 pub fn read(buf: &[u8], desc: &FieldDesc) -> Result<Self, FieldError> {
646 match desc.field_type {
647 FieldType::U8 => Ok(Self::U8(u8::read(buf, desc.offset)?)),
648 FieldType::U16 => Ok(Self::U16(u16::read(buf, desc.offset)?)),
649 FieldType::U32 => Ok(Self::U32(u32::read(buf, desc.offset)?)),
650 FieldType::U64 => Ok(Self::U64(u64::read(buf, desc.offset)?)),
651 FieldType::I8 => Ok(Self::I8(read_i8(buf, desc.offset)?)),
652 FieldType::I16 => Ok(Self::I16(read_i16_be(buf, desc.offset)?)),
653 FieldType::I32 => Ok(Self::I32(read_i32_be(buf, desc.offset)?)),
654 FieldType::I64 => Ok(Self::I64(read_i64_be(buf, desc.offset)?)),
655 FieldType::LEU16 => Ok(Self::U16(read_u16_le(buf, desc.offset)?)),
656 FieldType::LEU32 => Ok(Self::U32(read_u32_le(buf, desc.offset)?)),
657 FieldType::LEU64 => Ok(Self::U64(read_u64_le(buf, desc.offset)?)),
658 FieldType::U24 => Ok(Self::U32(read_u24_be(buf, desc.offset)?)),
659 FieldType::LEU24 => Ok(Self::U32(read_u24_le(buf, desc.offset)?)),
660 FieldType::Bool => Ok(Self::Bool(u8::read(buf, desc.offset)? != 0)),
661 FieldType::Mac => Ok(Self::Mac(MacAddress::read(buf, desc.offset)?)),
662 FieldType::Ipv4 => Ok(Self::Ipv4(Ipv4Addr::read(buf, desc.offset)?)),
663 FieldType::Ipv6 => Ok(Self::Ipv6(Ipv6Addr::read(buf, desc.offset)?)),
664 FieldType::Bytes => {
665 let field = BytesField::read_with_len(buf, desc.offset, desc.size)?;
666 Ok(Self::Bytes(field.0))
667 },
668 FieldType::Str => {
669 let field = BytesField::read_with_len(buf, desc.offset, desc.size)?;
670 Ok(Self::Str(String::from_utf8_lossy(&field.0).into_owned()))
671 },
672 FieldType::DnsName => {
673 let field = BytesField::read_with_len(buf, desc.offset, desc.size)?;
676 Ok(Self::Bytes(field.0))
677 },
678 }
679 }
680
681 pub fn read_bytes(buf: &[u8], offset: usize, len: usize) -> Result<Self, FieldError> {
683 let field = BytesField::read_with_len(buf, offset, len)?;
684 Ok(Self::Bytes(field.0))
685 }
686
687 pub fn write(&self, buf: &mut [u8], desc: &FieldDesc) -> Result<(), FieldError> {
689 match (self, desc.field_type) {
690 (Self::U8(v), FieldType::U8) => v.write(buf, desc.offset),
691 (Self::U16(v), FieldType::U16) => v.write(buf, desc.offset),
692 (Self::U32(v), FieldType::U32) => v.write(buf, desc.offset),
693 (Self::U64(v), FieldType::U64) => v.write(buf, desc.offset),
694 (Self::I8(v), FieldType::I8) => write_i8(*v, buf, desc.offset),
695 (Self::I16(v), FieldType::I16) => write_i16_be(*v, buf, desc.offset),
696 (Self::I32(v), FieldType::I32) => write_i32_be(*v, buf, desc.offset),
697 (Self::I64(v), FieldType::I64) => write_i64_be(*v, buf, desc.offset),
698 (Self::U16(v), FieldType::LEU16) => write_u16_le(*v, buf, desc.offset),
699 (Self::U32(v), FieldType::LEU32) => write_u32_le(*v, buf, desc.offset),
700 (Self::U64(v), FieldType::LEU64) => write_u64_le(*v, buf, desc.offset),
701 (Self::U32(v), FieldType::U24) => write_u24_be(*v, buf, desc.offset),
702 (Self::U32(v), FieldType::LEU24) => write_u24_le(*v, buf, desc.offset),
703 (Self::Bool(v), FieldType::Bool) => u8::from(*v).write(buf, desc.offset),
704 (Self::Mac(v), FieldType::Mac) => v.write(buf, desc.offset),
705 (Self::Ipv4(v), FieldType::Ipv4) => v.write(buf, desc.offset),
706 (Self::Ipv6(v), FieldType::Ipv6) => v.write(buf, desc.offset),
707 (Self::Bytes(v), FieldType::Bytes) => BytesField(v.clone()).write_to(buf, desc.offset),
708 (Self::Str(v), FieldType::Str) => {
709 BytesField(v.as_bytes().to_vec()).write_to(buf, desc.offset)
710 },
711 _ => Err(FieldError::TypeMismatch {
712 expected: desc.field_type.name(),
713 got: self.type_name(),
714 }),
715 }
716 }
717
718 pub fn write_bytes(bytes: &[u8], buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
720 BytesField::from_slice(bytes).write_to(buf, offset)
721 }
722
723 #[must_use]
724 pub const fn type_name(&self) -> &'static str {
725 match self {
726 Self::U8(_) => "u8",
727 Self::U16(_) => "u16",
728 Self::U32(_) => "u32",
729 Self::U64(_) => "u64",
730 Self::I8(_) => "i8",
731 Self::I16(_) => "i16",
732 Self::I32(_) => "i32",
733 Self::I64(_) => "i64",
734 Self::Bool(_) => "bool",
735 Self::Mac(_) => "MAC",
736 Self::Ipv4(_) => "IPv4",
737 Self::Ipv6(_) => "IPv6",
738 Self::Bytes(_) => "Bytes",
739 Self::Str(_) => "Str",
740 Self::List(_) => "List",
741 }
742 }
743
744 #[must_use]
745 pub fn as_u8(&self) -> Option<u8> {
746 match self {
747 Self::U8(v) => Some(*v),
748 _ => None,
749 }
750 }
751
752 #[must_use]
753 pub fn as_u16(&self) -> Option<u16> {
754 match self {
755 Self::U16(v) => Some(*v),
756 _ => None,
757 }
758 }
759
760 #[must_use]
761 pub fn as_u32(&self) -> Option<u32> {
762 match self {
763 Self::U32(v) => Some(*v),
764 _ => None,
765 }
766 }
767
768 #[must_use]
769 pub fn as_u64(&self) -> Option<u64> {
770 match self {
771 Self::U64(v) => Some(*v),
772 _ => None,
773 }
774 }
775
776 #[must_use]
777 pub fn as_mac(&self) -> Option<MacAddress> {
778 match self {
779 Self::Mac(v) => Some(*v),
780 _ => None,
781 }
782 }
783
784 #[must_use]
785 pub fn as_ipv4(&self) -> Option<Ipv4Addr> {
786 match self {
787 Self::Ipv4(v) => Some(*v),
788 _ => None,
789 }
790 }
791
792 #[must_use]
793 pub fn as_ipv6(&self) -> Option<Ipv6Addr> {
794 match self {
795 Self::Ipv6(v) => Some(*v),
796 _ => None,
797 }
798 }
799
800 #[must_use]
801 pub fn as_bytes(&self) -> Option<&[u8]> {
802 match self {
803 Self::Bytes(v) => Some(v),
804 _ => None,
805 }
806 }
807
808 #[must_use]
809 pub fn as_i8(&self) -> Option<i8> {
810 match self {
811 Self::I8(v) => Some(*v),
812 _ => None,
813 }
814 }
815
816 #[must_use]
817 pub fn as_i16(&self) -> Option<i16> {
818 match self {
819 Self::I16(v) => Some(*v),
820 _ => None,
821 }
822 }
823
824 #[must_use]
825 pub fn as_i32(&self) -> Option<i32> {
826 match self {
827 Self::I32(v) => Some(*v),
828 _ => None,
829 }
830 }
831
832 #[must_use]
833 pub fn as_i64(&self) -> Option<i64> {
834 match self {
835 Self::I64(v) => Some(*v),
836 _ => None,
837 }
838 }
839
840 #[must_use]
841 pub fn as_bool(&self) -> Option<bool> {
842 match self {
843 Self::Bool(v) => Some(*v),
844 _ => None,
845 }
846 }
847
848 #[must_use]
849 pub fn as_str(&self) -> Option<&str> {
850 match self {
851 Self::Str(v) => Some(v),
852 _ => None,
853 }
854 }
855
856 #[must_use]
857 pub fn as_list(&self) -> Option<&[FieldValue]> {
858 match self {
859 Self::List(v) => Some(v),
860 _ => None,
861 }
862 }
863
864 #[must_use]
866 pub fn to_bytes(&self) -> Vec<u8> {
867 match self {
868 Self::U8(v) => vec![*v],
869 Self::U16(v) => v.to_be_bytes().to_vec(),
870 Self::U32(v) => v.to_be_bytes().to_vec(),
871 Self::U64(v) => v.to_be_bytes().to_vec(),
872 Self::I8(v) => v.to_be_bytes().to_vec(),
873 Self::I16(v) => v.to_be_bytes().to_vec(),
874 Self::I32(v) => v.to_be_bytes().to_vec(),
875 Self::I64(v) => v.to_be_bytes().to_vec(),
876 Self::Bool(v) => vec![u8::from(*v)],
877 Self::Mac(v) => v.0.to_vec(),
878 Self::Ipv4(v) => v.octets().to_vec(),
879 Self::Ipv6(v) => v.octets().to_vec(),
880 Self::Bytes(v) => v.clone(),
881 Self::Str(v) => v.as_bytes().to_vec(),
882 Self::List(v) => v.iter().flat_map(FieldValue::to_bytes).collect(),
883 }
884 }
885}
886
887impl fmt::Display for FieldValue {
888 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
889 match self {
890 Self::U8(v) => write!(f, "{v}"),
891 Self::U16(v) => write!(f, "{v:#06x}"),
892 Self::U32(v) => write!(f, "{v:#010x}"),
893 Self::U64(v) => write!(f, "{v:#018x}"),
894 Self::I8(v) => write!(f, "{v}"),
895 Self::I16(v) => write!(f, "{v}"),
896 Self::I32(v) => write!(f, "{v}"),
897 Self::I64(v) => write!(f, "{v}"),
898 Self::Bool(v) => write!(f, "{v}"),
899 Self::Mac(v) => write!(f, "{v}"),
900 Self::Ipv4(v) => write!(f, "{v}"),
901 Self::Ipv6(v) => write!(f, "{v}"),
902 Self::Bytes(v) => {
903 write!(f, "0x")?;
904 for b in v {
905 write!(f, "{b:02x}")?;
906 }
907 Ok(())
908 },
909 Self::Str(v) => write!(f, "{v}"),
910 Self::List(v) => {
911 write!(f, "[")?;
912 for (i, item) in v.iter().enumerate() {
913 if i > 0 {
914 write!(f, ", ")?;
915 }
916 write!(f, "{item}")?;
917 }
918 write!(f, "]")
919 },
920 }
921 }
922}
923
924impl From<u8> for FieldValue {
926 fn from(v: u8) -> Self {
927 Self::U8(v)
928 }
929}
930impl From<u16> for FieldValue {
931 fn from(v: u16) -> Self {
932 Self::U16(v)
933 }
934}
935impl From<u32> for FieldValue {
936 fn from(v: u32) -> Self {
937 Self::U32(v)
938 }
939}
940impl From<u64> for FieldValue {
941 fn from(v: u64) -> Self {
942 Self::U64(v)
943 }
944}
945impl From<MacAddress> for FieldValue {
946 fn from(v: MacAddress) -> Self {
947 Self::Mac(v)
948 }
949}
950impl From<Ipv4Addr> for FieldValue {
951 fn from(v: Ipv4Addr) -> Self {
952 Self::Ipv4(v)
953 }
954}
955impl From<Ipv6Addr> for FieldValue {
956 fn from(v: Ipv6Addr) -> Self {
957 Self::Ipv6(v)
958 }
959}
960impl From<Vec<u8>> for FieldValue {
961 fn from(v: Vec<u8>) -> Self {
962 Self::Bytes(v)
963 }
964}
965impl From<&[u8]> for FieldValue {
966 fn from(v: &[u8]) -> Self {
967 Self::Bytes(v.to_vec())
968 }
969}
970impl From<i8> for FieldValue {
971 fn from(v: i8) -> Self {
972 Self::I8(v)
973 }
974}
975impl From<i16> for FieldValue {
976 fn from(v: i16) -> Self {
977 Self::I16(v)
978 }
979}
980impl From<i32> for FieldValue {
981 fn from(v: i32) -> Self {
982 Self::I32(v)
983 }
984}
985impl From<i64> for FieldValue {
986 fn from(v: i64) -> Self {
987 Self::I64(v)
988 }
989}
990impl From<bool> for FieldValue {
991 fn from(v: bool) -> Self {
992 Self::Bool(v)
993 }
994}
995impl From<String> for FieldValue {
996 fn from(v: String) -> Self {
997 Self::Str(v)
998 }
999}
1000impl From<&str> for FieldValue {
1001 fn from(v: &str) -> Self {
1002 Self::Str(v.to_string())
1003 }
1004}
1005
1006#[inline]
1011pub fn read_i8(buf: &[u8], offset: usize) -> Result<i8, FieldError> {
1012 Ok(u8::read(buf, offset)? as i8)
1013}
1014
1015#[inline]
1016pub fn write_i8(v: i8, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1017 (v as u8).write(buf, offset)
1018}
1019
1020#[inline]
1021pub fn read_i16_be(buf: &[u8], offset: usize) -> Result<i16, FieldError> {
1022 if buf.len() < offset + 2 {
1023 return Err(FieldError::BufferTooShort {
1024 offset,
1025 need: 2,
1026 have: buf.len(),
1027 });
1028 }
1029 Ok(i16::from_be_bytes([buf[offset], buf[offset + 1]]))
1030}
1031
1032#[inline]
1033pub fn write_i16_be(v: i16, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1034 if buf.len() < offset + 2 {
1035 return Err(FieldError::BufferTooShort {
1036 offset,
1037 need: 2,
1038 have: buf.len(),
1039 });
1040 }
1041 buf[offset..offset + 2].copy_from_slice(&v.to_be_bytes());
1042 Ok(())
1043}
1044
1045#[inline]
1046pub fn read_i32_be(buf: &[u8], offset: usize) -> Result<i32, FieldError> {
1047 if buf.len() < offset + 4 {
1048 return Err(FieldError::BufferTooShort {
1049 offset,
1050 need: 4,
1051 have: buf.len(),
1052 });
1053 }
1054 Ok(i32::from_be_bytes([
1055 buf[offset],
1056 buf[offset + 1],
1057 buf[offset + 2],
1058 buf[offset + 3],
1059 ]))
1060}
1061
1062#[inline]
1063pub fn write_i32_be(v: i32, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1064 if buf.len() < offset + 4 {
1065 return Err(FieldError::BufferTooShort {
1066 offset,
1067 need: 4,
1068 have: buf.len(),
1069 });
1070 }
1071 buf[offset..offset + 4].copy_from_slice(&v.to_be_bytes());
1072 Ok(())
1073}
1074
1075#[inline]
1076pub fn read_i64_be(buf: &[u8], offset: usize) -> Result<i64, FieldError> {
1077 if buf.len() < offset + 8 {
1078 return Err(FieldError::BufferTooShort {
1079 offset,
1080 need: 8,
1081 have: buf.len(),
1082 });
1083 }
1084 let mut bytes = [0u8; 8];
1085 bytes.copy_from_slice(&buf[offset..offset + 8]);
1086 Ok(i64::from_be_bytes(bytes))
1087}
1088
1089#[inline]
1090pub fn write_i64_be(v: i64, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1091 if buf.len() < offset + 8 {
1092 return Err(FieldError::BufferTooShort {
1093 offset,
1094 need: 8,
1095 have: buf.len(),
1096 });
1097 }
1098 buf[offset..offset + 8].copy_from_slice(&v.to_be_bytes());
1099 Ok(())
1100}
1101
1102#[inline]
1103pub fn read_u16_le(buf: &[u8], offset: usize) -> Result<u16, FieldError> {
1104 if buf.len() < offset + 2 {
1105 return Err(FieldError::BufferTooShort {
1106 offset,
1107 need: 2,
1108 have: buf.len(),
1109 });
1110 }
1111 Ok(u16::from_le_bytes([buf[offset], buf[offset + 1]]))
1112}
1113
1114#[inline]
1115pub fn write_u16_le(v: u16, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1116 if buf.len() < offset + 2 {
1117 return Err(FieldError::BufferTooShort {
1118 offset,
1119 need: 2,
1120 have: buf.len(),
1121 });
1122 }
1123 buf[offset..offset + 2].copy_from_slice(&v.to_le_bytes());
1124 Ok(())
1125}
1126
1127#[inline]
1128pub fn read_u32_le(buf: &[u8], offset: usize) -> Result<u32, FieldError> {
1129 if buf.len() < offset + 4 {
1130 return Err(FieldError::BufferTooShort {
1131 offset,
1132 need: 4,
1133 have: buf.len(),
1134 });
1135 }
1136 Ok(u32::from_le_bytes([
1137 buf[offset],
1138 buf[offset + 1],
1139 buf[offset + 2],
1140 buf[offset + 3],
1141 ]))
1142}
1143
1144#[inline]
1145pub fn write_u32_le(v: u32, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1146 if buf.len() < offset + 4 {
1147 return Err(FieldError::BufferTooShort {
1148 offset,
1149 need: 4,
1150 have: buf.len(),
1151 });
1152 }
1153 buf[offset..offset + 4].copy_from_slice(&v.to_le_bytes());
1154 Ok(())
1155}
1156
1157#[inline]
1158pub fn read_u64_le(buf: &[u8], offset: usize) -> Result<u64, FieldError> {
1159 if buf.len() < offset + 8 {
1160 return Err(FieldError::BufferTooShort {
1161 offset,
1162 need: 8,
1163 have: buf.len(),
1164 });
1165 }
1166 let mut bytes = [0u8; 8];
1167 bytes.copy_from_slice(&buf[offset..offset + 8]);
1168 Ok(u64::from_le_bytes(bytes))
1169}
1170
1171#[inline]
1172pub fn write_u64_le(v: u64, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1173 if buf.len() < offset + 8 {
1174 return Err(FieldError::BufferTooShort {
1175 offset,
1176 need: 8,
1177 have: buf.len(),
1178 });
1179 }
1180 buf[offset..offset + 8].copy_from_slice(&v.to_le_bytes());
1181 Ok(())
1182}
1183
1184#[inline]
1185pub fn read_u24_be(buf: &[u8], offset: usize) -> Result<u32, FieldError> {
1186 if buf.len() < offset + 3 {
1187 return Err(FieldError::BufferTooShort {
1188 offset,
1189 need: 3,
1190 have: buf.len(),
1191 });
1192 }
1193 Ok((u32::from(buf[offset]) << 16)
1194 | (u32::from(buf[offset + 1]) << 8)
1195 | u32::from(buf[offset + 2]))
1196}
1197
1198#[inline]
1199pub fn write_u24_be(v: u32, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1200 if buf.len() < offset + 3 {
1201 return Err(FieldError::BufferTooShort {
1202 offset,
1203 need: 3,
1204 have: buf.len(),
1205 });
1206 }
1207 buf[offset] = ((v >> 16) & 0xFF) as u8;
1208 buf[offset + 1] = ((v >> 8) & 0xFF) as u8;
1209 buf[offset + 2] = (v & 0xFF) as u8;
1210 Ok(())
1211}
1212
1213#[inline]
1214pub fn read_u24_le(buf: &[u8], offset: usize) -> Result<u32, FieldError> {
1215 if buf.len() < offset + 3 {
1216 return Err(FieldError::BufferTooShort {
1217 offset,
1218 need: 3,
1219 have: buf.len(),
1220 });
1221 }
1222 Ok(u32::from(buf[offset])
1223 | (u32::from(buf[offset + 1]) << 8)
1224 | (u32::from(buf[offset + 2]) << 16))
1225}
1226
1227#[inline]
1228pub fn write_u24_le(v: u32, buf: &mut [u8], offset: usize) -> Result<(), FieldError> {
1229 if buf.len() < offset + 3 {
1230 return Err(FieldError::BufferTooShort {
1231 offset,
1232 need: 3,
1233 have: buf.len(),
1234 });
1235 }
1236 buf[offset] = (v & 0xFF) as u8;
1237 buf[offset + 1] = ((v >> 8) & 0xFF) as u8;
1238 buf[offset + 2] = ((v >> 16) & 0xFF) as u8;
1239 Ok(())
1240}
1241
1242#[inline]
1251pub fn read_bits_be(buf: &[u8], bit_offset: usize, num_bits: usize) -> Result<u64, FieldError> {
1252 if num_bits == 0 || num_bits > 64 {
1253 return Err(FieldError::InvalidValue(format!(
1254 "num_bits must be 1..=64, got {num_bits}"
1255 )));
1256 }
1257 let end_bit = bit_offset + num_bits;
1258 let end_byte = end_bit.div_ceil(8);
1259 if end_byte > buf.len() {
1260 return Err(FieldError::BufferTooShort {
1261 offset: bit_offset / 8,
1262 need: end_byte,
1263 have: buf.len(),
1264 });
1265 }
1266
1267 let mut result: u64 = 0;
1268 for i in 0..num_bits {
1269 let bit_pos = bit_offset + i;
1270 let byte_idx = bit_pos / 8;
1271 let bit_idx = 7 - (bit_pos % 8); if (buf[byte_idx] >> bit_idx) & 1 != 0 {
1273 result |= 1u64 << (num_bits - 1 - i);
1274 }
1275 }
1276 Ok(result)
1277}
1278
1279#[inline]
1284pub fn write_bits_be(
1285 buf: &mut [u8],
1286 bit_offset: usize,
1287 num_bits: usize,
1288 value: u64,
1289) -> Result<(), FieldError> {
1290 if num_bits == 0 || num_bits > 64 {
1291 return Err(FieldError::InvalidValue(format!(
1292 "num_bits must be 1..=64, got {num_bits}"
1293 )));
1294 }
1295 let end_bit = bit_offset + num_bits;
1296 let end_byte = end_bit.div_ceil(8);
1297 if end_byte > buf.len() {
1298 return Err(FieldError::BufferTooShort {
1299 offset: bit_offset / 8,
1300 need: end_byte,
1301 have: buf.len(),
1302 });
1303 }
1304
1305 for i in 0..num_bits {
1306 let bit_pos = bit_offset + i;
1307 let byte_idx = bit_pos / 8;
1308 let bit_idx = 7 - (bit_pos % 8); let bit_val = (value >> (num_bits - 1 - i)) & 1;
1310 if bit_val != 0 {
1311 buf[byte_idx] |= 1 << bit_idx;
1312 } else {
1313 buf[byte_idx] &= !(1 << bit_idx);
1314 }
1315 }
1316 Ok(())
1317}
1318
1319#[inline]
1321pub fn read_bits_le(buf: &[u8], bit_offset: usize, num_bits: usize) -> Result<u64, FieldError> {
1322 if num_bits == 0 || num_bits > 64 {
1323 return Err(FieldError::InvalidValue(format!(
1324 "num_bits must be 1..=64, got {num_bits}"
1325 )));
1326 }
1327 let end_bit = bit_offset + num_bits;
1328 let end_byte = end_bit.div_ceil(8);
1329 if end_byte > buf.len() {
1330 return Err(FieldError::BufferTooShort {
1331 offset: bit_offset / 8,
1332 need: end_byte,
1333 have: buf.len(),
1334 });
1335 }
1336
1337 let mut result: u64 = 0;
1338 for i in 0..num_bits {
1339 let bit_pos = bit_offset + i;
1340 let byte_idx = bit_pos / 8;
1341 let bit_idx = bit_pos % 8; if (buf[byte_idx] >> bit_idx) & 1 != 0 {
1343 result |= 1u64 << i;
1344 }
1345 }
1346 Ok(result)
1347}
1348
1349#[inline]
1351pub fn write_bits_le(
1352 buf: &mut [u8],
1353 bit_offset: usize,
1354 num_bits: usize,
1355 value: u64,
1356) -> Result<(), FieldError> {
1357 if num_bits == 0 || num_bits > 64 {
1358 return Err(FieldError::InvalidValue(format!(
1359 "num_bits must be 1..=64, got {num_bits}"
1360 )));
1361 }
1362 let end_bit = bit_offset + num_bits;
1363 let end_byte = end_bit.div_ceil(8);
1364 if end_byte > buf.len() {
1365 return Err(FieldError::BufferTooShort {
1366 offset: bit_offset / 8,
1367 need: end_byte,
1368 have: buf.len(),
1369 });
1370 }
1371
1372 for i in 0..num_bits {
1373 let bit_pos = bit_offset + i;
1374 let byte_idx = bit_pos / 8;
1375 let bit_idx = bit_pos % 8; let bit_val = (value >> i) & 1;
1377 if bit_val != 0 {
1378 buf[byte_idx] |= 1 << bit_idx;
1379 } else {
1380 buf[byte_idx] &= !(1 << bit_idx);
1381 }
1382 }
1383 Ok(())
1384}
1385
1386#[cfg(test)]
1387mod tests {
1388 use super::*;
1389
1390 #[test]
1391 fn test_ipv6_field() {
1392 let ip = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
1393 let mut buf = [0u8; 20];
1394 ip.write(&mut buf, 2).unwrap();
1395 let read_ip = Ipv6Addr::read(&buf, 2).unwrap();
1396 assert_eq!(ip, read_ip);
1397 }
1398
1399 #[test]
1400 fn test_bytes_field() {
1401 let data = vec![0xde, 0xad, 0xbe, 0xef];
1402 let mut buf = [0u8; 10];
1403 BytesField(data.clone()).write_to(&mut buf, 2).unwrap();
1404 let read = BytesField::read_with_len(&buf, 2, 4).unwrap();
1405 assert_eq!(read.0, data);
1406 }
1407
1408 #[test]
1409 fn test_field_value_ipv6() {
1410 let ip = Ipv6Addr::LOCALHOST;
1411 let val = FieldValue::from(ip);
1412 assert_eq!(val.as_ipv6(), Some(ip));
1413 assert_eq!(val.type_name(), "IPv6");
1414 }
1415
1416 #[test]
1417 fn test_mac_multicast() {
1418 let mcast = MacAddress::from_ipv4_multicast(Ipv4Addr::new(224, 0, 0, 1));
1419 assert!(mcast.is_ipv4_multicast());
1420 assert!(mcast.is_multicast());
1421 }
1422
1423 #[test]
1424 fn test_u64_field() {
1425 let mut buf = [0u8; 10];
1426 let val: u64 = 0x0102030405060708;
1427 val.write(&mut buf, 1).unwrap();
1428 assert_eq!(u64::read(&buf, 1).unwrap(), val);
1429 }
1430
1431 #[test]
1432 fn test_i8_read_write() {
1433 let mut buf = [0u8; 4];
1434 write_i8(-42, &mut buf, 1).unwrap();
1435 assert_eq!(read_i8(&buf, 1).unwrap(), -42);
1436 write_i8(127, &mut buf, 0).unwrap();
1437 assert_eq!(read_i8(&buf, 0).unwrap(), 127);
1438 }
1439
1440 #[test]
1441 fn test_i16_read_write() {
1442 let mut buf = [0u8; 4];
1443 write_i16_be(-1234, &mut buf, 1).unwrap();
1444 assert_eq!(read_i16_be(&buf, 1).unwrap(), -1234);
1445 }
1446
1447 #[test]
1448 fn test_i32_read_write() {
1449 let mut buf = [0u8; 8];
1450 write_i32_be(-100_000, &mut buf, 2).unwrap();
1451 assert_eq!(read_i32_be(&buf, 2).unwrap(), -100_000);
1452 }
1453
1454 #[test]
1455 fn test_i64_read_write() {
1456 let mut buf = [0u8; 10];
1457 write_i64_be(-1_000_000_000_000, &mut buf, 1).unwrap();
1458 assert_eq!(read_i64_be(&buf, 1).unwrap(), -1_000_000_000_000);
1459 }
1460
1461 #[test]
1462 fn test_u16_le_read_write() {
1463 let mut buf = [0u8; 4];
1464 write_u16_le(0x0102, &mut buf, 1).unwrap();
1465 assert_eq!(buf[1], 0x02); assert_eq!(buf[2], 0x01);
1467 assert_eq!(read_u16_le(&buf, 1).unwrap(), 0x0102);
1468 }
1469
1470 #[test]
1471 fn test_u32_le_read_write() {
1472 let mut buf = [0u8; 6];
1473 write_u32_le(0x01020304, &mut buf, 1).unwrap();
1474 assert_eq!(read_u32_le(&buf, 1).unwrap(), 0x01020304);
1475 }
1476
1477 #[test]
1478 fn test_u64_le_read_write() {
1479 let mut buf = [0u8; 10];
1480 write_u64_le(0x0102030405060708, &mut buf, 1).unwrap();
1481 assert_eq!(read_u64_le(&buf, 1).unwrap(), 0x0102030405060708);
1482 }
1483
1484 #[test]
1485 fn test_u24_be_read_write() {
1486 let mut buf = [0u8; 5];
1487 write_u24_be(0x123456, &mut buf, 1).unwrap();
1488 assert_eq!(buf[1], 0x12);
1489 assert_eq!(buf[2], 0x34);
1490 assert_eq!(buf[3], 0x56);
1491 assert_eq!(read_u24_be(&buf, 1).unwrap(), 0x123456);
1492 }
1493
1494 #[test]
1495 fn test_u24_le_read_write() {
1496 let mut buf = [0u8; 5];
1497 write_u24_le(0x123456, &mut buf, 1).unwrap();
1498 assert_eq!(buf[1], 0x56); assert_eq!(buf[2], 0x34);
1500 assert_eq!(buf[3], 0x12);
1501 assert_eq!(read_u24_le(&buf, 1).unwrap(), 0x123456);
1502 }
1503
1504 #[test]
1505 fn test_read_bits_be() {
1506 let buf = [0xA5u8];
1508 assert_eq!(read_bits_be(&buf, 0, 1).unwrap(), 1); assert_eq!(read_bits_be(&buf, 1, 1).unwrap(), 0); assert_eq!(read_bits_be(&buf, 0, 4).unwrap(), 0b1010); assert_eq!(read_bits_be(&buf, 4, 4).unwrap(), 0b0101); assert_eq!(read_bits_be(&buf, 0, 8).unwrap(), 0xA5); }
1514
1515 #[test]
1516 fn test_write_bits_be() {
1517 let mut buf = [0u8; 2];
1518 write_bits_be(&mut buf, 0, 4, 0b1010).unwrap();
1519 write_bits_be(&mut buf, 4, 4, 0b0101).unwrap();
1520 assert_eq!(buf[0], 0xA5);
1521 }
1522
1523 #[test]
1524 fn test_bits_be_cross_byte() {
1525 let buf = [0b1100_0011, 0b1010_0101];
1526 assert_eq!(read_bits_be(&buf, 6, 4).unwrap(), 0b1110);
1528 }
1529
1530 #[test]
1531 fn test_read_bits_le() {
1532 let buf = [0xA5u8]; assert_eq!(read_bits_le(&buf, 0, 1).unwrap(), 1); assert_eq!(read_bits_le(&buf, 1, 1).unwrap(), 0); assert_eq!(read_bits_le(&buf, 0, 4).unwrap(), 0b0101); assert_eq!(read_bits_le(&buf, 4, 4).unwrap(), 0b1010); }
1539
1540 #[test]
1541 fn test_write_bits_le() {
1542 let mut buf = [0u8; 2];
1543 write_bits_le(&mut buf, 0, 3, 0b101).unwrap();
1545 assert_eq!(buf[0] & 0x07, 0b101);
1546 }
1547
1548 #[test]
1549 fn test_field_value_new_types() {
1550 assert_eq!(FieldValue::from(-42i8).as_i8(), Some(-42));
1551 assert_eq!(FieldValue::from(-1000i16).as_i16(), Some(-1000));
1552 assert_eq!(FieldValue::from(-100_000i32).as_i32(), Some(-100_000));
1553 assert_eq!(FieldValue::from(-1i64).as_i64(), Some(-1));
1554 assert_eq!(FieldValue::from(true).as_bool(), Some(true));
1555 assert_eq!(FieldValue::from(false).as_bool(), Some(false));
1556 assert_eq!(FieldValue::from("hello").as_str(), Some("hello"));
1557 }
1558
1559 #[test]
1560 fn test_field_value_list() {
1561 let list = FieldValue::List(vec![
1562 FieldValue::U16(1),
1563 FieldValue::U16(2),
1564 FieldValue::U16(3),
1565 ]);
1566 assert_eq!(list.as_list().unwrap().len(), 3);
1567 assert_eq!(list.to_string(), "[0x0001, 0x0002, 0x0003]");
1568 }
1569
1570 #[test]
1571 fn test_buffer_too_short_errors() {
1572 let buf = [0u8; 2];
1573 assert!(read_u24_be(&buf, 0).is_err());
1574 assert!(read_u32_le(&buf, 0).is_err());
1575 assert!(read_i32_be(&buf, 0).is_err());
1576 assert!(read_bits_be(&buf, 0, 24).is_err());
1577 }
1578}