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    #[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    /// Check if this is an IPv4 multicast MAC (01:00:5e:xx:xx:xx)
100    #[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    /// Check if this is an IPv6 multicast MAC (33:33:xx:xx:xx:xx)
107    #[inline]
108    #[must_use]
109    pub fn is_ipv6_multicast(&self) -> bool {
110        self.0[0] == 0x33 && self.0[1] == 0x33
111    }
112
113    /// Create multicast MAC for IPv4 multicast address
114    #[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    /// Create multicast MAC for IPv6 multicast address
121    #[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    /// Parse MAC from string (e.g., "00:11:22:33:44:55" or "00-11-22-33-44-55")
128    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            // Handle bare hex string like "001122334455"
136            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
211/// Trait for reading/writing protocol fields from raw buffers.
212pub trait Field: Sized {
213    /// The size of this field in bytes (None for variable-length fields).
214    const SIZE: Option<usize>;
215
216    /// Read the field value from the buffer at the given offset.
217    fn read(buf: &[u8], offset: usize) -> Result<Self, FieldError>;
218
219    /// Write the field value to the buffer at the given offset.
220    fn write(&self, buf: &mut [u8], offset: usize) -> Result<(), FieldError>;
221}
222
223// ============================================================================
224// Field implementations for primitive types
225// ============================================================================
226
227impl 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// ============================================================================
449// Variable-length bytes field
450// ============================================================================
451
452/// A variable-length byte field
453#[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// ============================================================================
515// Field descriptor for dynamic field definitions
516// ============================================================================
517
518/// Describes a field's position and type within a protocol header.
519#[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/// Supported field types for dynamic access.
528#[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/// A dynamically-typed field value.
624#[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    /// Read a field value from buffer using the field descriptor.
645    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                // DnsName requires special handling with the full packet buffer
674                // Return raw bytes; callers should use dns::name module directly
675                let field = BytesField::read_with_len(buf, desc.offset, desc.size)?;
676                Ok(Self::Bytes(field.0))
677            },
678        }
679    }
680
681    /// Read a bytes field with explicit length
682    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    /// Write a field value to buffer using the field descriptor.
688    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    /// Write bytes to buffer at offset
719    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    /// Convert to bytes representation
865    #[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
924// Conversion traits
925impl 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// ============================================================================
1007// Little-endian and signed integer helpers
1008// ============================================================================
1009
1010#[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// ============================================================================
1243// Bit field reader/writer for arbitrary bit-width fields
1244// ============================================================================
1245
1246/// Read arbitrary number of bits from a byte buffer at a bit offset.
1247/// `bit_offset` is the starting bit position (0 = MSB of first byte).
1248/// `num_bits` is 1..=64.
1249/// Returns the value right-aligned in a u64.
1250#[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); // MSB first
1272        if (buf[byte_idx] >> bit_idx) & 1 != 0 {
1273            result |= 1u64 << (num_bits - 1 - i);
1274        }
1275    }
1276    Ok(result)
1277}
1278
1279/// Write arbitrary number of bits to a byte buffer at a bit offset.
1280/// `bit_offset` is the starting bit position (0 = MSB of first byte).
1281/// `num_bits` is 1..=64.
1282/// `value` is right-aligned.
1283#[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); // MSB first
1309        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/// Read bits in little-endian bit order (LSB of first byte = bit 0).
1320#[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; // LSB first
1342        if (buf[byte_idx] >> bit_idx) & 1 != 0 {
1343            result |= 1u64 << i;
1344        }
1345    }
1346    Ok(result)
1347}
1348
1349/// Write bits in little-endian bit order (LSB of first byte = bit 0).
1350#[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; // LSB first
1376        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); // LE: low byte first
1466        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); // LE: low byte first
1499        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        // byte 0xA5 = 1010_0101
1507        let buf = [0xA5u8];
1508        assert_eq!(read_bits_be(&buf, 0, 1).unwrap(), 1); // bit 7 = 1
1509        assert_eq!(read_bits_be(&buf, 1, 1).unwrap(), 0); // bit 6 = 0
1510        assert_eq!(read_bits_be(&buf, 0, 4).unwrap(), 0b1010); // top nibble
1511        assert_eq!(read_bits_be(&buf, 4, 4).unwrap(), 0b0101); // bottom nibble
1512        assert_eq!(read_bits_be(&buf, 0, 8).unwrap(), 0xA5); // full byte
1513    }
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        // Read 4 bits spanning bytes: bits 6,7 of byte 0 + bits 0,1 of byte 1
1527        assert_eq!(read_bits_be(&buf, 6, 4).unwrap(), 0b1110);
1528    }
1529
1530    #[test]
1531    fn test_read_bits_le() {
1532        // For LE bit ordering, bit 0 is LSB of first byte
1533        let buf = [0xA5u8]; // 1010_0101
1534        assert_eq!(read_bits_le(&buf, 0, 1).unwrap(), 1); // bit 0 (LSB) = 1
1535        assert_eq!(read_bits_le(&buf, 1, 1).unwrap(), 0); // bit 1 = 0
1536        assert_eq!(read_bits_le(&buf, 0, 4).unwrap(), 0b0101); // low nibble
1537        assert_eq!(read_bits_le(&buf, 4, 4).unwrap(), 0b1010); // high nibble
1538    }
1539
1540    #[test]
1541    fn test_write_bits_le() {
1542        let mut buf = [0u8; 2];
1543        // Write 3 bits at bit offset 0 (LE): value 5 = 0b101
1544        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}