Skip to main content

stackforge_core/layer/
field.rs

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