senax_encoder/
lib.rs

1//! # senax-encoder
2//!
3//! A fast, compact, and schema-evolution-friendly binary serialization library for Rust.
4//!
5//! - Supports struct/enum encoding with field/variant IDs for forward/backward compatibility
6//! - Efficient encoding for primitives, collections, Option, String, bytes, and popular crates (chrono, uuid, ulid, rust_decimal, indexmap)
7//! - Custom derive macros for ergonomic usage
8//! - Feature-gated support for optional dependencies
9//!
10//! ## Attribute Macros
11//!
12//! You can control encoding/decoding behavior using the following attributes:
13//!
14//! - `#[senax(id = N)]` — Assigns a custom field or variant ID (u32 or u8, see below). Ensures stable wire format across versions.
15//! - `#[senax(default)]` — If a field is missing during decoding, its value is set to `Default::default()` instead of causing an error. For `Option<T>`, this means `None`.
16//! - `#[senax(skip_encode)]` — This field is not written during encoding. On decode, it is set to `Default::default()`.
17//! - `#[senax(skip_decode)]` — This field is ignored during decoding and always set to `Default::default()`. It is still encoded if present.
18//! - `#[senax(rename = "name")]` — Use the given string as the logical field/variant name for ID calculation. Useful for renaming fields/variants while keeping the same wire format.
19//! - `#[senax(u8)]` — On structs/enums, encodes field/variant IDs as `u8` instead of `u32` (for compactness, up to 255 IDs; 0 is reserved for terminator).
20//!
21//! ## Feature Flags
22//!
23//! The following optional features enable support for popular crates and types:
24//!
25//! - `all` — Enables all optional features below at once: `indexmap`, `chrono`, `rust_decimal`, `uuid`, `ulid`.
26//! - `chrono` — Enables encoding/decoding of `chrono::DateTime`, `NaiveDate`, and `NaiveTime` types.
27//! - `uuid` — Enables encoding/decoding of `uuid::Uuid`.
28//! - `ulid` — Enables encoding/decoding of `ulid::Ulid` (shares the same tag as UUID for binary compatibility).
29//! - `rust_decimal` — Enables encoding/decoding of `rust_decimal::Decimal`.
30//! - `indexmap` — Enables encoding/decoding of `IndexMap` and `IndexSet` collections.
31//!
32//! ## Example
33//! ```rust
34//! use senax_encoder::{Encoder, Decoder, Encode, Decode};
35//! use bytes::BytesMut;
36//!
37//! #[derive(Encode, Decode, PartialEq, Debug)]
38//! struct MyStruct {
39//!     id: u32,
40//!     name: String,
41//! }
42//!
43//! let value = MyStruct { id: 42, name: "hello".to_string() };
44//! let mut buf = BytesMut::new();
45//! value.encode(&mut buf).unwrap();
46//! let decoded = MyStruct::decode(&mut buf.freeze()).unwrap();
47//! assert_eq!(value, decoded);
48//! ```
49
50use bytes::{Buf, BufMut, Bytes, BytesMut};
51#[cfg(feature = "chrono")]
52use chrono::{DateTime, Local, NaiveDate, NaiveTime, Timelike, Utc};
53#[cfg(feature = "indexmap")]
54use indexmap::{IndexMap, IndexSet};
55#[cfg(feature = "rust_decimal")]
56use rust_decimal::Decimal;
57pub use senax_encoder_derive::{Decode, Encode};
58use std::collections::HashMap;
59use std::collections::{BTreeMap, BTreeSet, HashSet};
60use thiserror::Error;
61#[cfg(feature = "ulid")]
62use ulid::Ulid;
63#[cfg(feature = "uuid")]
64use uuid::Uuid;
65
66/// Error type for all encoding and decoding operations in this crate.
67///
68/// This error type is returned by all `Encode` and `Decode` trait methods.
69/// It covers I/O errors, encoding/decoding logic errors, and buffer underflow.
70#[derive(Debug, Error)]
71pub enum EncoderError {
72    /// The value could not be encoded (e.g., unsupported type or logic error).
73    #[error("Encode error: {0}")]
74    Encode(String),
75    /// The value could not be decoded (e.g., invalid data, type mismatch, or schema evolution error).
76    #[error("Decode error: {0}")]
77    Decode(String),
78    /// The buffer did not contain enough data to complete the operation.
79    #[error("Insufficient data in buffer")]
80    InsufficientData,
81}
82
83/// The result type used throughout this crate for encode/decode operations.
84///
85/// All `Encode` and `Decode` trait methods return this type.
86pub type Result<T> = std::result::Result<T, EncoderError>;
87
88/// Trait for types that can be encoded into the senax binary format.
89///
90/// Implement this trait for your type to enable serialization.
91/// Most users should use `#[derive(Encode)]` instead of manual implementation.
92///
93/// # Errors
94/// Returns `EncoderError` if the value cannot be encoded.
95pub trait Encoder {
96    /// Encode the value into the given buffer.
97    ///
98    /// # Arguments
99    /// * `writer` - The buffer to write the encoded bytes into.
100    fn encode(&self, writer: &mut BytesMut) -> Result<()>;
101}
102
103/// Trait for types that can be decoded from the senax binary format.
104///
105/// Implement this trait for your type to enable deserialization.
106/// Most users should use `#[derive(Decode)]` instead of manual implementation.
107///
108/// # Errors
109/// Returns `EncoderError` if the value cannot be decoded or the data is invalid.
110pub trait Decoder: Sized {
111    /// Decode the value from the given buffer.
112    ///
113    /// # Arguments
114    /// * `reader` - The buffer to read the encoded bytes from.
115    fn decode(reader: &mut Bytes) -> Result<Self>;
116}
117
118/// Type tags used in the senax binary format.
119///
120/// These tags are written as the first byte of each encoded value to identify its type and optimize decoding.
121/// Most users do not need to use these directly.
122///
123/// - Primitives, Option, String, Vec, arrays, maps, structs, enums, and feature types each have their own tag(s).
124/// - Tags are stable and part of the wire format.
125pub const TAG_NONE: u8 = 1;
126///< Option::None
127pub const TAG_SOME: u8 = 2;
128///< Option::Some
129pub const TAG_ZERO: u8 = 3;
130///< 0 for numbers, false for bool
131pub const TAG_ONE: u8 = 4;
132///< 1 for numbers, true for bool
133// 5-130: Values 2-127 (compact encoding for small unsigned integers)
134pub const TAG_U8_2_BASE: u8 = 5; // 2
135pub const TAG_U8_127: u8 = 130; // 127
136pub const TAG_U8: u8 = 131;
137///< u8 (full range)
138pub const TAG_U16: u8 = 132;
139///< u16
140pub const TAG_U32: u8 = 133;
141///< u32
142pub const TAG_U64: u8 = 134;
143///< u64
144pub const TAG_U128: u8 = 135;
145///< u128
146pub const TAG_NEGATIVE: u8 = 136;
147///< Negative signed integer (bit-inverted encoding)
148pub const TAG_F32: u8 = 137;
149///< f32
150pub const TAG_F64: u8 = 138;
151///< f64
152pub const TAG_STRING_BASE: u8 = 139;
153///< Short string (length in tag)
154pub const TAG_STRING_LONG: u8 = 180;
155///< Long string (length encoded)
156pub const TAG_BINARY: u8 = 181;
157///< Vec<u8> or Bytes
158pub const TAG_STRUCT_UNIT: u8 = 182;
159///< Unit struct
160pub const TAG_STRUCT_NAMED: u8 = 183;
161///< Named struct
162pub const TAG_STRUCT_UNNAMED: u8 = 184;
163///< Tuple struct
164pub const TAG_ENUM: u8 = 185;
165///< C-like enum (unit variants)
166pub const TAG_ENUM_NAMED: u8 = 186;
167///< Enum with named fields
168pub const TAG_ENUM_UNNAMED: u8 = 187;
169///< Enum with tuple fields
170pub const TAG_ARRAY_VEC_SET_BASE: u8 = 188;
171///< Short array/vec/set (length in tag)
172pub const TAG_ARRAY_VEC_SET_LONG: u8 = 194;
173///< Long array/vec/set (length encoded)
174pub const TAG_TUPLE: u8 = 195;
175///< Tuple
176pub const TAG_MAP: u8 = 196;
177///< Map (HashMap, BTreeMap, IndexMap)
178pub const TAG_CHRONO_DATETIME: u8 = 197;
179///< chrono::DateTime
180pub const TAG_CHRONO_NAIVE_DATE: u8 = 198;
181///< chrono::NaiveDate
182pub const TAG_CHRONO_NAIVE_TIME: u8 = 199;
183///< chrono::NaiveTime
184pub const TAG_DECIMAL: u8 = 200;
185///< rust_decimal::Decimal
186pub const TAG_UUID: u8 = 201;
187///< uuid::Uuid, ulid::Ulid
188
189// --- bool ---
190/// Encodes a `bool` as a single tag byte: `TAG_ZERO` for `false`, `TAG_ONE` for `true`.
191impl Encoder for bool {
192    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
193        let tag = if !*self { TAG_ZERO } else { TAG_ONE }; // 3: false, 4: true
194        writer.put_u8(tag);
195        Ok(())
196    }
197}
198/// Decodes a `bool` from a single tag byte.
199///
200/// # Errors
201/// Returns an error if the tag is not `TAG_ZERO` or `TAG_ONE`.
202impl Decoder for bool {
203    fn decode(reader: &mut Bytes) -> Result<Self> {
204        if reader.remaining() == 0 {
205            return Err(EncoderError::InsufficientData);
206        }
207        let tag = reader.get_u8();
208        match tag {
209            TAG_ZERO => Ok(false),
210            TAG_ONE => Ok(true),
211            other => Err(EncoderError::Decode(format!(
212                "Expected bool tag ({} or {}), got {}",
213                TAG_ZERO, TAG_ONE, other
214            ))),
215        }
216    }
217}
218
219// --- Common decode functions ---
220/// Decodes a `u8` value from a tag and buffer.
221/// Used internally for compact integer decoding.
222///
223/// # Errors
224/// Returns an error if the tag is not valid for a `u8`.
225#[inline]
226fn decode_u8_from_tag(tag: u8, reader: &mut Bytes) -> Result<u8> {
227    if (TAG_ZERO..=TAG_ZERO + 127).contains(&tag) {
228        Ok(tag - TAG_ZERO)
229    } else if tag == TAG_U8 {
230        if reader.remaining() < 1 {
231            return Err(EncoderError::InsufficientData);
232        }
233        let stored_val = reader.get_u8();
234        stored_val.checked_add(128).ok_or_else(|| {
235            EncoderError::Decode(format!("u8 TAG_U8 value overflow: {}", stored_val))
236        })
237    } else {
238        Err(EncoderError::Decode(format!(
239            "Unexpected tag for u8: {}",
240            tag
241        )))
242    }
243}
244/// Decodes a `u16` value from a tag and buffer.
245/// Used internally for compact integer decoding.
246#[inline(never)]
247fn decode_u16_from_tag(tag: u8, reader: &mut Bytes) -> Result<u16> {
248    if (TAG_ZERO..=TAG_ZERO + 127).contains(&tag) {
249        Ok((tag - TAG_ZERO) as u16)
250    } else if tag == TAG_U8 {
251        if reader.remaining() < 1 {
252            return Err(EncoderError::InsufficientData);
253        }
254        Ok(reader.get_u8() as u16 + 128)
255    } else if tag == TAG_U16 {
256        if reader.remaining() < 2 {
257            return Err(EncoderError::InsufficientData);
258        }
259        Ok(reader.get_u16_le())
260    } else {
261        Err(EncoderError::Decode(format!(
262            "Unexpected tag for u16: {}",
263            tag
264        )))
265    }
266}
267/// Decodes a `u32` value from a tag and buffer.
268/// Used internally for compact integer decoding.
269#[inline]
270fn decode_u32_from_tag(tag: u8, reader: &mut Bytes) -> Result<u32> {
271    if (TAG_ZERO..=TAG_ZERO + 127).contains(&tag) {
272        Ok((tag - TAG_ZERO) as u32)
273    } else if tag == TAG_U8 {
274        if reader.remaining() < 1 {
275            return Err(EncoderError::InsufficientData);
276        }
277        Ok(reader.get_u8() as u32 + 128)
278    } else if tag == TAG_U16 {
279        if reader.remaining() < 2 {
280            return Err(EncoderError::InsufficientData);
281        }
282        Ok(reader.get_u16_le() as u32)
283    } else if tag == TAG_U32 {
284        if reader.remaining() < 4 {
285            return Err(EncoderError::InsufficientData);
286        }
287        Ok(reader.get_u32_le())
288    } else {
289        Err(EncoderError::Decode(format!(
290            "Unexpected tag for u32: {}",
291            tag
292        )))
293    }
294}
295/// Decodes a `u64` value from a tag and buffer.
296/// Used internally for compact integer decoding.
297#[inline]
298fn decode_u64_from_tag(tag: u8, reader: &mut Bytes) -> Result<u64> {
299    if (TAG_ZERO..=TAG_ZERO + 127).contains(&tag) {
300        Ok((tag - TAG_ZERO) as u64)
301    } else if tag == TAG_U8 {
302        if reader.remaining() < 1 {
303            return Err(EncoderError::InsufficientData);
304        }
305        Ok(reader.get_u8() as u64 + 128)
306    } else if tag == TAG_U16 {
307        if reader.remaining() < 2 {
308            return Err(EncoderError::InsufficientData);
309        }
310        Ok(reader.get_u16_le() as u64)
311    } else if tag == TAG_U32 {
312        if reader.remaining() < 4 {
313            return Err(EncoderError::InsufficientData);
314        }
315        Ok(reader.get_u32_le() as u64)
316    } else if tag == TAG_U64 {
317        if reader.remaining() < 8 {
318            return Err(EncoderError::InsufficientData);
319        }
320        Ok(reader.get_u64_le())
321    } else {
322        Err(EncoderError::Decode(format!(
323            "Unexpected tag for u64: {}",
324            tag
325        )))
326    }
327}
328/// Decodes a `u128` value from a tag and buffer.
329/// Used internally for compact integer decoding.
330#[inline(never)]
331fn decode_u128_from_tag(tag: u8, reader: &mut Bytes) -> Result<u128> {
332    if (TAG_ZERO..=TAG_ZERO + 127).contains(&tag) {
333        Ok((tag - TAG_ZERO) as u128)
334    } else if tag == TAG_U8 {
335        if reader.remaining() < 1 {
336            return Err(EncoderError::InsufficientData);
337        }
338        Ok(reader.get_u8() as u128 + 128)
339    } else if tag == TAG_U16 {
340        if reader.remaining() < 2 {
341            return Err(EncoderError::InsufficientData);
342        }
343        Ok(reader.get_u16_le() as u128)
344    } else if tag == TAG_U32 {
345        if reader.remaining() < 4 {
346            return Err(EncoderError::InsufficientData);
347        }
348        Ok(reader.get_u32_le() as u128)
349    } else if tag == TAG_U64 {
350        if reader.remaining() < 8 {
351            return Err(EncoderError::InsufficientData);
352        }
353        Ok(reader.get_u64_le() as u128)
354    } else if tag == TAG_U128 {
355        if reader.remaining() < 16 {
356            return Err(EncoderError::InsufficientData);
357        }
358        Ok(reader.get_u128_le())
359    } else {
360        Err(EncoderError::Decode(format!(
361            "Unexpected tag for u128: {}",
362            tag
363        )))
364    }
365}
366
367// --- Unsigned integer types ---
368/// Encodes unsigned integers using a compact variable-length format.
369///
370/// - Values 0/1 are encoded as `TAG_ZERO`/`TAG_ONE` (1 byte)
371/// - 2..=127 are encoded as a single tag byte (1 byte)
372/// - Larger values use `TAG_U8`, `TAG_U16`, `TAG_U32`, `TAG_U64`, or `TAG_U128` with the value in little-endian
373/// - The encoding is stable and compatible across platforms
374impl Encoder for u8 {
375    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
376        if *self <= 127 {
377            writer.put_u8(TAG_ZERO + *self);
378        } else {
379            writer.put_u8(TAG_U8);
380            writer.put_u8(*self - 128);
381        }
382        Ok(())
383    }
384}
385/// Decodes a `u8` from the compact format.
386impl Decoder for u8 {
387    fn decode(reader: &mut Bytes) -> Result<Self> {
388        if reader.remaining() == 0 {
389            return Err(EncoderError::InsufficientData);
390        }
391        let tag = reader.get_u8();
392        decode_u8_from_tag(tag, reader)
393    }
394}
395/// See `u8` for format details.
396impl Encoder for u16 {
397    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
398        if *self <= 127 {
399            writer.put_u8(TAG_ZERO + (*self as u8));
400        } else if *self <= 255 + 128 {
401            writer.put_u8(TAG_U8);
402            writer.put_u8((*self - 128) as u8);
403        } else {
404            writer.put_u8(TAG_U16);
405            writer.put_u16_le(*self);
406        }
407        Ok(())
408    }
409}
410impl Decoder for u16 {
411    fn decode(reader: &mut Bytes) -> Result<Self> {
412        if reader.remaining() == 0 {
413            return Err(EncoderError::InsufficientData);
414        }
415        let tag = reader.get_u8();
416        decode_u16_from_tag(tag, reader)
417    }
418}
419impl Encoder for u32 {
420    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
421        if *self <= 127 {
422            writer.put_u8(TAG_ZERO + (*self as u8));
423        } else if *self <= 255 + 128 {
424            writer.put_u8(TAG_U8);
425            writer.put_u8((*self - 128) as u8);
426        } else if *self <= 65535 {
427            writer.put_u8(TAG_U16);
428            writer.put_u16_le(*self as u16);
429        } else {
430            writer.put_u8(TAG_U32);
431            writer.put_u32_le(*self);
432        }
433        Ok(())
434    }
435}
436impl Decoder for u32 {
437    fn decode(reader: &mut Bytes) -> Result<Self> {
438        if reader.remaining() == 0 {
439            return Err(EncoderError::InsufficientData);
440        }
441        let tag = reader.get_u8();
442        decode_u32_from_tag(tag, reader)
443    }
444}
445impl Encoder for u64 {
446    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
447        if *self <= 127 {
448            writer.put_u8(TAG_ZERO + (*self as u8));
449        } else if *self <= 255 + 128 {
450            writer.put_u8(TAG_U8);
451            writer.put_u8((*self - 128) as u8);
452        } else if *self <= 65535 {
453            writer.put_u8(TAG_U16);
454            writer.put_u16_le(*self as u16);
455        } else if *self <= 4294967295 {
456            writer.put_u8(TAG_U32);
457            writer.put_u32_le(*self as u32);
458        } else {
459            writer.put_u8(TAG_U64);
460            writer.put_u64_le(*self);
461        }
462        Ok(())
463    }
464}
465impl Decoder for u64 {
466    fn decode(reader: &mut Bytes) -> Result<Self> {
467        if reader.remaining() == 0 {
468            return Err(EncoderError::InsufficientData);
469        }
470        let tag = reader.get_u8();
471        decode_u64_from_tag(tag, reader)
472    }
473}
474impl Encoder for u128 {
475    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
476        if *self <= 127 {
477            writer.put_u8(TAG_ZERO + (*self as u8));
478        } else if *self <= 255 + 128 {
479            writer.put_u8(TAG_U8);
480            writer.put_u8((*self - 128) as u8);
481        } else if *self <= 65535 {
482            writer.put_u8(TAG_U16);
483            writer.put_u16_le(*self as u16);
484        } else if *self <= 4294967295 {
485            writer.put_u8(TAG_U32);
486            writer.put_u32_le(*self as u32);
487        } else if *self <= 18446744073709551615 {
488            writer.put_u8(TAG_U64);
489            writer.put_u64_le(*self as u64);
490        } else {
491            writer.put_u8(TAG_U128);
492            writer.put_u128_le(*self);
493        }
494        Ok(())
495    }
496}
497impl Decoder for u128 {
498    fn decode(reader: &mut Bytes) -> Result<Self> {
499        if reader.remaining() == 0 {
500            return Err(EncoderError::InsufficientData);
501        }
502        let tag = reader.get_u8();
503        decode_u128_from_tag(tag, reader)
504    }
505}
506/// Encodes `usize` using the platform's pointer width, but always as a portable integer format.
507impl Encoder for usize {
508    #[inline]
509    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
510        if usize::BITS == u64::BITS {
511            let v = *self as u64;
512            v.encode(writer)
513        } else if usize::BITS == u32::BITS {
514            let v = *self as u32;
515            v.encode(writer)
516        } else if usize::BITS == u16::BITS {
517            let v = *self as u16;
518            v.encode(writer)
519        } else {
520            let v = *self as u128;
521            v.encode(writer)
522        }
523    }
524}
525impl Decoder for usize {
526    fn decode(reader: &mut Bytes) -> Result<Self> {
527        if reader.remaining() == 0 {
528            return Err(EncoderError::InsufficientData);
529        }
530        let tag = reader.get_u8();
531        if usize::BITS == u64::BITS {
532            Ok(decode_u64_from_tag(tag, reader)? as usize)
533        } else if usize::BITS == u32::BITS {
534            Ok(decode_u32_from_tag(tag, reader)? as usize)
535        } else if usize::BITS == u16::BITS {
536            Ok(decode_u16_from_tag(tag, reader)? as usize)
537        } else {
538            Ok(decode_u128_from_tag(tag, reader)? as usize)
539        }
540    }
541}
542
543// --- Signed integer types (bit-inverted encoding) ---
544/// Encodes signed integers using bit-inverted encoding for negative values.
545///
546/// - Non-negative values (>= 0) are encoded as unsigned integers
547/// - Negative values use `TAG_NEGATIVE` and bit-inverted encoding
548impl Encoder for i8 {
549    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
550        if *self >= 0 {
551            (*self as u8).encode(writer)
552        } else {
553            writer.put_u8(TAG_NEGATIVE);
554            let inv = !(*self as u8);
555            inv.encode(writer)
556        }
557    }
558}
559/// Decodes a `i8` from the bit-inverted encoding.
560///
561/// # Errors
562/// Returns an error if the tag is not valid for an `i8`.
563impl Decoder for i8 {
564    fn decode(reader: &mut Bytes) -> Result<Self> {
565        if reader.remaining() == 0 {
566            return Err(EncoderError::InsufficientData);
567        }
568        let tag = reader.get_u8();
569        match tag {
570            TAG_NEGATIVE => {
571                let inv = u8::decode(reader)?;
572                Ok(!inv as i8)
573            }
574            t => {
575                let v = decode_u8_from_tag(t, reader)?;
576                if v > i8::MAX as u8 {
577                    return Err(EncoderError::Decode(format!("Value {} too large for i8", v)));
578                }
579                Ok(v as i8)
580            }
581        }
582    }
583}
584// i16
585impl Encoder for i16 {
586    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
587        if *self >= 0 {
588            (*self as u16).encode(writer)
589        } else {
590            writer.put_u8(TAG_NEGATIVE);
591            let inv = !(*self as u16);
592            inv.encode(writer)
593        }
594    }
595}
596impl Decoder for i16 {
597    fn decode(reader: &mut Bytes) -> Result<Self> {
598        if reader.remaining() == 0 {
599            return Err(EncoderError::InsufficientData);
600        }
601        let tag = reader.get_u8();
602        match tag {
603            TAG_NEGATIVE => {
604                let inv = u16::decode(reader)?;
605                Ok(!inv as i16)
606            }
607            t => {
608                let v = decode_u16_from_tag(t, reader)?;
609                if v > i16::MAX as u16 {
610                    return Err(EncoderError::Decode(format!("Value {} too large for i16", v)));
611                }
612                Ok(v as i16)
613            }
614        }
615    }
616}
617// i32
618impl Encoder for i32 {
619    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
620        if *self >= 0 {
621            (*self as u32).encode(writer)
622        } else {
623            writer.put_u8(TAG_NEGATIVE);
624            let inv = !(*self as u32);
625            inv.encode(writer)
626        }
627    }
628}
629impl Decoder for i32 {
630    fn decode(reader: &mut Bytes) -> Result<Self> {
631        if reader.remaining() == 0 {
632            return Err(EncoderError::InsufficientData);
633        }
634        let tag = reader.get_u8();
635        match tag {
636            TAG_NEGATIVE => {
637                let inv = u32::decode(reader)?;
638                Ok(!inv as i32)
639            }
640            t => {
641                let v = decode_u32_from_tag(t, reader)?;
642                if v > i32::MAX as u32 {
643                    return Err(EncoderError::Decode(format!("Value {} too large for i32", v)));
644                }
645                Ok(v as i32)
646            }
647        }
648    }
649}
650// i64
651impl Encoder for i64 {
652    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
653        if *self >= 0 {
654            (*self as u64).encode(writer)
655        } else {
656            writer.put_u8(TAG_NEGATIVE);
657            let inv = !(*self as u64);
658            inv.encode(writer)
659        }
660    }
661}
662impl Decoder for i64 {
663    fn decode(reader: &mut Bytes) -> Result<Self> {
664        if reader.remaining() == 0 {
665            return Err(EncoderError::InsufficientData);
666        }
667        let tag = reader.get_u8();
668        match tag {
669            TAG_NEGATIVE => {
670                let inv = u64::decode(reader)?;
671                Ok(!inv as i64)
672            }
673            t => {
674                let v = decode_u64_from_tag(t, reader)?;
675                if v > i64::MAX as u64 {
676                    return Err(EncoderError::Decode(format!("Value {} too large for i64", v)));
677                }
678                Ok(v as i64)
679            }
680        }
681    }
682}
683// i128
684impl Encoder for i128 {
685    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
686        if *self >= 0 {
687            (*self as u128).encode(writer)
688        } else {
689            writer.put_u8(TAG_NEGATIVE);
690            let inv = !(*self as u128);
691            inv.encode(writer)
692        }
693    }
694}
695impl Decoder for i128 {
696    fn decode(reader: &mut Bytes) -> Result<Self> {
697        if reader.remaining() == 0 {
698            return Err(EncoderError::InsufficientData);
699        }
700        let tag = reader.get_u8();
701        match tag {
702            TAG_NEGATIVE => {
703                let inv = u128::decode(reader)?;
704                Ok(!inv as i128)
705            }
706            t => {
707                let v = decode_u128_from_tag(t, reader)?;
708                if v > i128::MAX as u128 {
709                    return Err(EncoderError::Decode(format!("Value {} too large for i128", v)));
710                }
711                Ok(v as i128)
712            }
713        }
714    }
715}
716// isize
717impl Encoder for isize {
718    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
719        if usize::BITS == u64::BITS {
720            let v = *self as i64;
721            v.encode(writer)
722        } else if usize::BITS == u32::BITS {
723            let v = *self as i32;
724            v.encode(writer)
725        } else if usize::BITS == u16::BITS {
726            let v = *self as i16;
727            v.encode(writer)
728        } else {
729            let v = *self as i128;
730            v.encode(writer)
731        }
732    }
733}
734impl Decoder for isize {
735    fn decode(reader: &mut Bytes) -> Result<Self> {
736        if reader.remaining() == 0 {
737            return Err(EncoderError::InsufficientData);
738        }
739        if usize::BITS == u64::BITS {
740            Ok(i64::decode(reader)? as isize)
741        } else if usize::BITS == u32::BITS {
742            Ok(i32::decode(reader)? as isize)
743        } else if usize::BITS == u16::BITS {
744            Ok(i16::decode(reader)? as isize)
745        } else {
746            Ok(i128::decode(reader)? as isize)
747        }
748    }
749}
750
751// --- f32/f64 ---
752/// Encodes an `f32` as a tag and 4 bytes (little-endian IEEE 754).
753impl Encoder for f32 {
754    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
755        writer.put_u8(TAG_F32);
756        writer.put_f32_le(*self);
757        Ok(())
758    }
759}
760/// Decodes an `f32` from either 4 or 8 bytes (accepts f64 for compatibility).
761impl Decoder for f32 {
762    fn decode(reader: &mut Bytes) -> Result<Self> {
763        if reader.remaining() == 0 {
764            return Err(EncoderError::InsufficientData);
765        }
766        let tag = reader.get_u8();
767        if tag == TAG_F32 {
768            if reader.remaining() < 4 {
769                return Err(EncoderError::InsufficientData);
770            }
771            let mut bytes = [0u8; 4];
772            reader.copy_to_slice(&mut bytes);
773            Ok(f32::from_le_bytes(bytes))
774        } else if tag == TAG_F64 {
775            if reader.remaining() < 8 {
776                return Err(EncoderError::InsufficientData);
777            }
778            let mut bytes = [0u8; 8];
779            reader.copy_to_slice(&mut bytes);
780            Ok(f64::from_le_bytes(bytes) as f32)
781        } else {
782            Err(EncoderError::Decode(format!(
783                "Expected f32/f64 tag ({} or {}), got {}",
784                TAG_F32, TAG_F64, tag
785            )))
786        }
787    }
788}
789/// Encodes an `f64` as a tag and 8 bytes (little-endian IEEE 754).
790impl Encoder for f64 {
791    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
792        writer.put_u8(TAG_F64);
793        writer.put_f64_le(*self);
794        Ok(())
795    }
796}
797/// Decodes an `f64` from either 8 or 4 bytes (accepts f32 for compatibility).
798impl Decoder for f64 {
799    fn decode(reader: &mut Bytes) -> Result<Self> {
800        if reader.remaining() == 0 {
801            return Err(EncoderError::InsufficientData);
802        }
803        let tag = reader.get_u8();
804        if tag == TAG_F64 {
805            if reader.remaining() < 8 {
806                return Err(EncoderError::InsufficientData);
807            }
808            let mut bytes = [0u8; 8];
809            reader.copy_to_slice(&mut bytes);
810            Ok(f64::from_le_bytes(bytes))
811        } else if tag == TAG_F32 {
812            if reader.remaining() < 4 {
813                return Err(EncoderError::InsufficientData);
814            }
815            let mut bytes = [0u8; 4];
816            reader.copy_to_slice(&mut bytes);
817            Ok(f32::from_le_bytes(bytes) as f64)
818        } else {
819            Err(EncoderError::Decode(format!(
820                "Expected f64/f32 tag ({} or {}), got {}",
821                TAG_F64, TAG_F32, tag
822            )))
823        }
824    }
825}
826
827// --- String ---
828/// Encodes a `String` as UTF-8 with a length prefix (short strings use a single tag byte).
829impl Encoder for String {
830    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
831        let len = self.len();
832        let max_short = (TAG_STRING_LONG - TAG_STRING_BASE - 1) as usize;
833        if len <= max_short {
834            let tag = TAG_STRING_BASE + len as u8; // 9..=29
835            writer.put_u8(tag);
836            writer.put_slice(self.as_bytes());
837        } else {
838            writer.put_u8(TAG_STRING_LONG);
839            len.encode(writer)?;
840            writer.put_slice(self.as_bytes());
841        }
842        Ok(())
843    }
844}
845/// Decodes a `String` from the senax binary format.
846impl Decoder for String {
847    fn decode(reader: &mut Bytes) -> Result<Self> {
848        if reader.remaining() == 0 {
849            return Err(EncoderError::InsufficientData);
850        }
851        let tag = reader.get_u8();
852        let len = if (TAG_STRING_BASE..TAG_STRING_LONG).contains(&tag) {
853            (tag - TAG_STRING_BASE) as usize
854        } else if tag == TAG_STRING_LONG {
855            usize::decode(reader)?
856        } else {
857            return Err(EncoderError::Decode(format!(
858                "Expected String tag ({}..={}), got {}",
859                TAG_STRING_BASE, TAG_STRING_LONG, tag
860            )));
861        };
862        if reader.remaining() < len {
863            return Err(EncoderError::InsufficientData);
864        }
865        let mut bytes = vec![0u8; len];
866        if len > 0 {
867            reader.copy_to_slice(&mut bytes);
868        }
869        String::from_utf8(bytes).map_err(|e| EncoderError::Decode(e.to_string()))
870    }
871}
872
873// --- Option ---
874/// Encodes an `Option<T>` as a tag byte followed by the value if present.
875impl<T: Encoder> Encoder for Option<T> {
876    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
877        match self {
878            Some(value) => {
879                writer.put_u8(TAG_SOME);
880                value.encode(writer)
881            }
882            None => {
883                writer.put_u8(TAG_NONE);
884                Ok(())
885            }
886        }
887    }
888}
889/// Decodes an `Option<T>` from the senax binary format.
890impl<T: Decoder> Decoder for Option<T> {
891    fn decode(reader: &mut Bytes) -> Result<Self> {
892        if reader.remaining() == 0 {
893            return Err(EncoderError::InsufficientData); // Not even a tag
894        }
895        let tag = reader.get_u8();
896        match tag {
897            TAG_NONE => Ok(None),
898            TAG_SOME => {
899                if reader.remaining() == 0 {
900                    // Check before T::decode if only TAG_SOME was present
901                    return Err(EncoderError::InsufficientData);
902                }
903                Ok(Some(T::decode(reader)?))
904            }
905            other => Err(EncoderError::Decode(format!(
906                "Expected Option tag ({} or {}), got {}",
907                TAG_NONE, TAG_SOME, other
908            ))),
909        }
910    }
911}
912
913// --- Vec<T> ---
914/// Encodes a `Vec<T>` as a length-prefixed sequence. `Vec<u8>` is optimized as binary.
915impl<T: Encoder + 'static> Encoder for Vec<T> {
916    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
917        if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u8>() {
918            writer.put_u8(TAG_BINARY);
919            let len = self.len();
920            len.encode(writer)?;
921            let bytes =
922                unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
923            writer.put_slice(bytes);
924            Ok(())
925        } else {
926            let len = self.len();
927            let max_short = (TAG_ARRAY_VEC_SET_LONG - TAG_ARRAY_VEC_SET_BASE - 1) as usize;
928            if len <= max_short {
929                let tag = TAG_ARRAY_VEC_SET_BASE + len as u8;
930                writer.put_u8(tag);
931                for item in self {
932                    item.encode(writer)?;
933                }
934            } else {
935                writer.put_u8(TAG_ARRAY_VEC_SET_LONG);
936                len.encode(writer)?;
937                for item in self {
938                    item.encode(writer)?;
939                }
940            }
941            Ok(())
942        }
943    }
944}
945/// Decodes a `Vec<T>` from the senax binary format.
946impl<T: Decoder + 'static> Decoder for Vec<T> {
947    fn decode(reader: &mut Bytes) -> Result<Self> {
948        if reader.remaining() == 0 {
949            return Err(EncoderError::InsufficientData);
950        }
951        let tag = reader.get_u8();
952        if tag == TAG_BINARY && std::any::TypeId::of::<T>() == std::any::TypeId::of::<u8>() {
953            let len = usize::decode(reader)?;
954            let mut vec = vec![0u8; len];
955            reader.copy_to_slice(&mut vec);
956            let ptr = vec.as_mut_ptr() as *mut T;
957            let len = vec.len();
958            let cap = vec.capacity();
959            std::mem::forget(vec);
960            unsafe { Ok(Vec::from_raw_parts(ptr, len, cap)) }
961        } else if (TAG_ARRAY_VEC_SET_BASE..TAG_ARRAY_VEC_SET_LONG).contains(&tag) {
962            let len = (tag - TAG_ARRAY_VEC_SET_BASE) as usize;
963            let mut vec = Vec::with_capacity(len);
964            for _ in 0..len {
965                vec.push(T::decode(reader)?);
966            }
967            Ok(vec)
968        } else if tag == TAG_ARRAY_VEC_SET_LONG {
969            let len = usize::decode(reader)?;
970            let mut vec = Vec::with_capacity(len);
971            for _ in 0..len {
972                vec.push(T::decode(reader)?);
973            }
974            Ok(vec)
975        } else {
976            Err(EncoderError::Decode(format!(
977                "Expected Vec tag ({}..={} or {}), got {}",
978                TAG_ARRAY_VEC_SET_BASE, TAG_ARRAY_VEC_SET_LONG, TAG_BINARY, tag
979            )))
980        }
981    }
982}
983
984// --- Array ---
985/// Encodes a fixed-size array as a length-prefixed sequence.
986impl<T: Encoder, const N: usize> Encoder for [T; N] {
987    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
988        let max_short = (TAG_ARRAY_VEC_SET_LONG - TAG_ARRAY_VEC_SET_BASE - 1) as usize;
989        if N <= max_short {
990            let tag = TAG_ARRAY_VEC_SET_BASE + N as u8;
991            writer.put_u8(tag);
992            for item in self {
993                item.encode(writer)?;
994            }
995        } else {
996            writer.put_u8(TAG_ARRAY_VEC_SET_LONG);
997            N.encode(writer)?;
998            for item in self {
999                item.encode(writer)?;
1000            }
1001        }
1002        Ok(())
1003    }
1004}
1005/// Decodes a fixed-size array from the senax binary format.
1006impl<T: Decoder, const N: usize> Decoder for [T; N] {
1007    fn decode(reader: &mut Bytes) -> Result<Self> {
1008        if reader.remaining() == 0 {
1009            return Err(EncoderError::InsufficientData);
1010        }
1011        let tag = reader.get_u8();
1012        let len = if (TAG_ARRAY_VEC_SET_BASE..TAG_ARRAY_VEC_SET_LONG).contains(&tag) {
1013            (tag - TAG_ARRAY_VEC_SET_BASE) as usize
1014        } else if tag == TAG_ARRAY_VEC_SET_LONG {
1015            usize::decode(reader)?
1016        } else {
1017            return Err(EncoderError::Decode(format!(
1018                "Expected Array tag ({}..={}), got {}",
1019                TAG_ARRAY_VEC_SET_BASE, TAG_ARRAY_VEC_SET_LONG, tag
1020            )));
1021        };
1022        if len != N {
1023            return Err(EncoderError::Decode(format!(
1024                "Array length mismatch: expected {}, got {}",
1025                N, len
1026            )));
1027        }
1028        let mut array = Vec::with_capacity(N);
1029        for _ in 0..N {
1030            array.push(T::decode(reader)?);
1031        }
1032        array
1033            .try_into()
1034            .map_err(|_| EncoderError::Decode("Failed to convert Vec to array".to_string()))
1035    }
1036}
1037
1038// --- Tuple ---
1039/// Implements encoding/decoding for tuples up to 10 elements.
1040///
1041/// Each tuple is encoded as a length-prefixed sequence of its elements.
1042macro_rules! impl_tuple {
1043    () => {
1044impl Encoder for () {
1045    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1046                writer.put_u8(TAG_TUPLE);
1047                0usize.encode(writer)?;
1048        Ok(())
1049    }
1050}
1051impl Decoder for () {
1052    fn decode(reader: &mut Bytes) -> Result<Self> {
1053        if reader.remaining() == 0 {
1054            return Err(EncoderError::InsufficientData);
1055        }
1056        let tag = reader.get_u8();
1057                if tag != TAG_TUPLE {
1058                    return Err(EncoderError::Decode(format!("Expected Tuple tag ({}), got {}", TAG_TUPLE, tag)));
1059                }
1060                let len = usize::decode(reader)?;
1061                if len != 0 {
1062                    return Err(EncoderError::Decode(format!("Expected 0-tuple but got {}-tuple", len)));
1063        }
1064        Ok(())
1065    }
1066}
1067    };
1068    ($($T:ident : $idx:tt),+) => {
1069        impl<$($T: Encoder),+> Encoder for ($($T,)+) {
1070    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1071                writer.put_u8(TAG_TUPLE);
1072                let count = count_args!($($T),+);
1073                count.encode(writer)?;
1074                $(
1075                    self.$idx.encode(writer)?;
1076                )+
1077        Ok(())
1078    }
1079}
1080        impl<$($T: Decoder),+> Decoder for ($($T,)+) {
1081    fn decode(reader: &mut Bytes) -> Result<Self> {
1082        if reader.remaining() == 0 {
1083            return Err(EncoderError::InsufficientData);
1084        }
1085        let tag = reader.get_u8();
1086                if tag != TAG_TUPLE {
1087                    return Err(EncoderError::Decode(format!("Expected Tuple tag ({}), got {}", TAG_TUPLE, tag)));
1088                }
1089                let len = usize::decode(reader)?;
1090                let expected_len = count_args!($($T),+);
1091                if len != expected_len {
1092                    return Err(EncoderError::Decode(format!("Expected {}-tuple but got {}-tuple", expected_len, len)));
1093                }
1094                Ok(($(
1095                    $T::decode(reader)?,
1096                )+))
1097            }
1098        }
1099    };
1100}
1101
1102macro_rules! count_args {
1103    () => { 0 };
1104    ($head:ident $(, $tail:ident)*) => { 1 + count_args!($($tail),*) };
1105}
1106
1107// Generate tuple implementations for 0 to 10 elements
1108impl_tuple!();
1109impl_tuple!(T0: 0);
1110impl_tuple!(T0: 0, T1: 1);
1111impl_tuple!(T0: 0, T1: 1, T2: 2);
1112impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3);
1113impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4);
1114impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5);
1115impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6);
1116impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7);
1117impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8);
1118impl_tuple!(T0: 0, T1: 1, T2: 2, T3: 3, T4: 4, T5: 5, T6: 6, T7: 7, T8: 8, T9: 9);
1119
1120// --- Map (HashMap) ---
1121/// Encodes a map as a length-prefixed sequence of key-value pairs.
1122impl<K: Encoder, V: Encoder> Encoder for HashMap<K, V> {
1123    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1124        writer.put_u8(TAG_MAP);
1125        let len = self.len();
1126        len.encode(writer)?;
1127        for (k, v) in self {
1128            k.encode(writer)?;
1129            v.encode(writer)?;
1130        }
1131        Ok(())
1132    }
1133}
1134/// Decodes a map from the senax binary format.
1135impl<K: Decoder + Eq + std::hash::Hash, V: Decoder> Decoder for HashMap<K, V> {
1136    fn decode(reader: &mut Bytes) -> Result<Self> {
1137        if reader.remaining() == 0 {
1138            return Err(EncoderError::InsufficientData);
1139        }
1140        let tag = reader.get_u8();
1141        if tag != TAG_MAP {
1142            return Err(EncoderError::Decode(format!(
1143                "Expected Map tag ({}), got {}",
1144                TAG_MAP, tag
1145            )));
1146        }
1147        let len = usize::decode(reader)?;
1148        let mut map = HashMap::with_capacity(len);
1149        for _ in 0..len {
1150            let k = K::decode(reader)?;
1151            let v = V::decode(reader)?;
1152            map.insert(k, v);
1153        }
1154        Ok(map)
1155    }
1156}
1157// --- Enum ---
1158// Enum is handled by proc-macro with tag TAG_ENUM (see proc-macro side)
1159// 32: Enum
1160
1161/// Writes a `u32` in little-endian format without a tag.
1162///
1163/// This is used internally for struct/enum field/variant IDs.
1164pub fn write_u32_le(writer: &mut BytesMut, value: u32) -> Result<()> {
1165    writer.put_u32_le(value);
1166    Ok(())
1167}
1168
1169/// Reads a `u32` in little-endian format without a tag.
1170///
1171/// This is used internally for struct/enum field/variant IDs.
1172pub fn read_u32_le(reader: &mut Bytes) -> Result<u32> {
1173    if reader.remaining() < 4 {
1174        return Err(EncoderError::InsufficientData);
1175    }
1176    Ok(reader.get_u32_le())
1177}
1178
1179/// Skips a value of any type in the senax binary format.
1180///
1181/// This is used for forward/backward compatibility when unknown fields/variants are encountered.
1182///
1183/// # Errors
1184/// Returns an error if the value cannot be skipped (e.g., insufficient data).
1185pub fn skip_value(reader: &mut Bytes) -> Result<()> {
1186    if reader.remaining() == 0 {
1187        return Err(EncoderError::InsufficientData);
1188    }
1189    let tag = reader.get_u8();
1190    match tag {
1191        TAG_ZERO | TAG_ONE => Ok(()),
1192        TAG_U8_2_BASE..=TAG_U8_127 => Ok(()),
1193        TAG_U8 => {
1194            if reader.remaining() < 1 {
1195                return Err(EncoderError::InsufficientData);
1196            }
1197            reader.advance(1);
1198            Ok(())
1199        }
1200        TAG_U16 => {
1201            if reader.remaining() < 2 {
1202                return Err(EncoderError::InsufficientData);
1203            }
1204            reader.advance(2);
1205            Ok(())
1206        }
1207        TAG_U32 => {
1208            if reader.remaining() < 4 {
1209                return Err(EncoderError::InsufficientData);
1210            }
1211            reader.advance(4);
1212            Ok(())
1213        }
1214        TAG_U64 => {
1215            if reader.remaining() < 8 {
1216                return Err(EncoderError::InsufficientData);
1217            }
1218            reader.advance(8);
1219            Ok(())
1220        }
1221        TAG_U128 => {
1222            if reader.remaining() < 16 {
1223                return Err(EncoderError::InsufficientData);
1224            }
1225            reader.advance(16);
1226            Ok(())
1227        }
1228        TAG_F32 => {
1229            if reader.remaining() < 4 {
1230                return Err(EncoderError::InsufficientData);
1231            }
1232            reader.advance(4);
1233            Ok(())
1234        }
1235        TAG_F64 => {
1236            if reader.remaining() < 8 {
1237                return Err(EncoderError::InsufficientData);
1238            }
1239            reader.advance(8);
1240            Ok(())
1241        }
1242        TAG_STRING_BASE..=TAG_STRING_LONG => {
1243            let len = if tag < TAG_STRING_LONG {
1244                (tag - TAG_STRING_BASE) as usize
1245            } else {
1246                usize::decode(reader)?
1247            };
1248            if reader.remaining() < len {
1249                return Err(EncoderError::InsufficientData);
1250            }
1251            reader.advance(len);
1252            Ok(())
1253        }
1254        TAG_BINARY => {
1255            let len = usize::decode(reader)?;
1256            if reader.remaining() < len {
1257                return Err(EncoderError::InsufficientData);
1258            }
1259            reader.advance(len);
1260            Ok(())
1261        }
1262        TAG_ARRAY_VEC_SET_BASE..=TAG_ARRAY_VEC_SET_LONG => {
1263            let len = if tag < TAG_ARRAY_VEC_SET_LONG {
1264                (tag - TAG_ARRAY_VEC_SET_BASE) as usize
1265            } else {
1266                usize::decode(reader)?
1267            };
1268            for _ in 0..len {
1269                skip_value(reader)?;
1270            }
1271            Ok(())
1272        }
1273        TAG_STRUCT_UNIT => Ok(()),
1274        TAG_STRUCT_NAMED => {
1275            loop {
1276                if reader.remaining() < 4 {
1277                    return Err(EncoderError::InsufficientData);
1278                } // field_id
1279                let field_id = read_u32_le(reader)?;
1280                if field_id == 0 {
1281                    break;
1282                }
1283                skip_value(reader)?;
1284            }
1285            Ok(())
1286        }
1287        TAG_STRUCT_UNNAMED => {
1288            let field_count = usize::decode(reader)?;
1289            for _ in 0..field_count {
1290                skip_value(reader)?;
1291            }
1292            Ok(())
1293        }
1294        TAG_ENUM => {
1295            if reader.remaining() < 4 {
1296                return Err(EncoderError::InsufficientData);
1297            } // variant_id
1298            let _variant_id = read_u32_le(reader)?;
1299            Ok(())
1300        }
1301        TAG_ENUM_NAMED => {
1302            if reader.remaining() < 4 {
1303                return Err(EncoderError::InsufficientData);
1304            } // variant_id
1305            let _variant_id = read_u32_le(reader)?;
1306            loop {
1307                if reader.remaining() < 4 {
1308                    return Err(EncoderError::InsufficientData);
1309                } // field_id
1310                let field_id = read_u32_le(reader)?;
1311                if field_id == 0 {
1312                    break;
1313                }
1314                skip_value(reader)?;
1315            }
1316            Ok(())
1317        }
1318        TAG_ENUM_UNNAMED => {
1319            if reader.remaining() < 4 {
1320                return Err(EncoderError::InsufficientData);
1321            } // variant_id
1322            let _variant_id = read_u32_le(reader)?;
1323            let field_count = usize::decode(reader)?;
1324            for _ in 0..field_count {
1325                skip_value(reader)?;
1326            }
1327            Ok(())
1328        }
1329        TAG_TUPLE => {
1330            let len = usize::decode(reader)?;
1331            for _ in 0..len {
1332                skip_value(reader)?;
1333            }
1334            Ok(())
1335        }
1336        TAG_MAP => {
1337            let len = usize::decode(reader)?;
1338            for _ in 0..len {
1339                skip_value(reader)?; // key
1340                skip_value(reader)?; // value
1341            }
1342            Ok(())
1343        }
1344        TAG_CHRONO_DATETIME => {
1345            if reader.remaining() < 12 {
1346                return Err(EncoderError::InsufficientData);
1347            } // Approximation for i64 + u32, could be more precise
1348            let _timestamp_seconds = i64::decode(reader)?;
1349            let _timestamp_nanos = u32::decode(reader)?;
1350            Ok(())
1351        }
1352        TAG_CHRONO_NAIVE_DATE => {
1353            if reader.remaining() < 8 {
1354                return Err(EncoderError::InsufficientData);
1355            } // Approximation for i64
1356            let _days_from_epoch = i64::decode(reader)?;
1357            Ok(())
1358        }
1359        TAG_CHRONO_NAIVE_TIME => {
1360            if reader.remaining() < 8 {
1361                return Err(EncoderError::InsufficientData);
1362            } // Approximation for u32 + u32
1363            let _seconds_from_midnight = u32::decode(reader)?;
1364            let _nanoseconds = u32::decode(reader)?;
1365            Ok(())
1366        }
1367        TAG_DECIMAL => {
1368            if reader.remaining() < 20 {
1369                return Err(EncoderError::InsufficientData);
1370            } // Approximation for i128 + u32
1371            let _mantissa = i128::decode(reader)?;
1372            let _scale = u32::decode(reader)?;
1373            Ok(())
1374        }
1375        TAG_UUID => {
1376            // Covers ULID as well
1377            if reader.remaining() < 16 {
1378                return Err(EncoderError::InsufficientData);
1379            }
1380            reader.advance(16);
1381            Ok(())
1382        }
1383        TAG_NONE | TAG_SOME => {
1384            // These should have been handled by Option<T> decode or skip_value for T
1385            // For TAG_NONE, it's fine. For TAG_SOME, we need to skip the inner value.
1386            if tag == TAG_SOME {
1387                skip_value(reader)?;
1388            }
1389            Ok(())
1390        }
1391        _ => Err(EncoderError::Decode(format!(
1392            "skip_value: unknown or unhandled tag {}",
1393            tag
1394        ))),
1395    }
1396}
1397
1398// --- HashSet, BTreeSet, IndexSet ---
1399/// Encodes a set as a length-prefixed sequence of elements.
1400impl<T: Encoder + Eq + std::hash::Hash> Encoder for HashSet<T> {
1401    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1402        let len = self.len();
1403        let max_short = (TAG_ARRAY_VEC_SET_LONG - TAG_ARRAY_VEC_SET_BASE - 1) as usize;
1404        if len <= max_short {
1405            let tag = TAG_ARRAY_VEC_SET_BASE + len as u8;
1406            writer.put_u8(tag);
1407            for v in self {
1408                v.encode(writer)?;
1409            }
1410        } else {
1411            writer.put_u8(TAG_ARRAY_VEC_SET_LONG);
1412            len.encode(writer)?;
1413            for v in self {
1414                v.encode(writer)?;
1415            }
1416        }
1417        Ok(())
1418    }
1419}
1420/// Decodes a set from the senax binary format.
1421impl<T: Decoder + Eq + std::hash::Hash + 'static> Decoder for HashSet<T> {
1422    fn decode(reader: &mut Bytes) -> Result<Self> {
1423        let vec: Vec<T> = Vec::decode(reader)?;
1424        Ok(vec.into_iter().collect())
1425    }
1426}
1427// --- BTreeSet ---
1428impl<T: Encoder + Ord> Encoder for BTreeSet<T> {
1429    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1430        let len = self.len();
1431        let max_short = (TAG_ARRAY_VEC_SET_LONG - TAG_ARRAY_VEC_SET_BASE - 1) as usize;
1432        if len <= max_short {
1433            let tag = TAG_ARRAY_VEC_SET_BASE + len as u8;
1434            writer.put_u8(tag);
1435            for v in self {
1436                v.encode(writer)?;
1437            }
1438        } else {
1439            writer.put_u8(TAG_ARRAY_VEC_SET_LONG);
1440            len.encode(writer)?;
1441            for v in self {
1442                v.encode(writer)?;
1443            }
1444        }
1445        Ok(())
1446    }
1447}
1448impl<T: Decoder + Ord + 'static> Decoder for BTreeSet<T> {
1449    fn decode(reader: &mut Bytes) -> Result<Self> {
1450        let vec: Vec<T> = Vec::decode(reader)?;
1451        Ok(vec.into_iter().collect())
1452    }
1453}
1454// --- IndexSet ---
1455#[cfg(feature = "indexmap")]
1456impl<T: Encoder + Eq + std::hash::Hash> Encoder for IndexSet<T> {
1457    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1458        let len = self.len();
1459        let max_short = (TAG_ARRAY_VEC_SET_LONG - TAG_ARRAY_VEC_SET_BASE - 1) as usize;
1460        if len <= max_short {
1461            let tag = TAG_ARRAY_VEC_SET_BASE + len as u8;
1462            writer.put_u8(tag);
1463            for v in self {
1464                v.encode(writer)?;
1465            }
1466        } else {
1467            writer.put_u8(TAG_ARRAY_VEC_SET_LONG);
1468            len.encode(writer)?;
1469            for v in self {
1470                v.encode(writer)?;
1471            }
1472        }
1473        Ok(())
1474    }
1475}
1476#[cfg(feature = "indexmap")]
1477impl<T: Decoder + Eq + std::hash::Hash + 'static> Decoder for IndexSet<T> {
1478    fn decode(reader: &mut Bytes) -> Result<Self> {
1479        let vec: Vec<T> = Vec::decode(reader)?;
1480        Ok(vec.into_iter().collect())
1481    }
1482}
1483// --- BTreeMap ---
1484impl<K: Encoder + Ord, V: Encoder> Encoder for BTreeMap<K, V> {
1485    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1486        writer.put_u8(TAG_MAP);
1487        let len = self.len();
1488        len.encode(writer)?;
1489        for (k, v) in self {
1490            k.encode(writer)?;
1491            v.encode(writer)?;
1492        }
1493        Ok(())
1494    }
1495}
1496impl<K: Decoder + Ord, V: Decoder> Decoder for BTreeMap<K, V> {
1497    fn decode(reader: &mut Bytes) -> Result<Self> {
1498        if reader.remaining() == 0 {
1499            return Err(EncoderError::InsufficientData);
1500        }
1501        let tag = reader.get_u8();
1502        if tag != TAG_MAP {
1503            return Err(EncoderError::Decode(format!(
1504                "Expected Map tag ({}), got {}",
1505                TAG_MAP, tag
1506            )));
1507        }
1508        let len = usize::decode(reader)?;
1509        let mut map = BTreeMap::new();
1510        for _ in 0..len {
1511            let k = K::decode(reader)?;
1512            let v = V::decode(reader)?;
1513            map.insert(k, v);
1514        }
1515        Ok(map)
1516    }
1517}
1518// --- IndexMap ---
1519#[cfg(feature = "indexmap")]
1520impl<K: Encoder + Eq + std::hash::Hash, V: Encoder> Encoder for IndexMap<K, V> {
1521    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1522        writer.put_u8(TAG_MAP);
1523        let len = self.len();
1524        len.encode(writer)?;
1525        for (k, v) in self {
1526            k.encode(writer)?;
1527            v.encode(writer)?;
1528        }
1529        Ok(())
1530    }
1531}
1532#[cfg(feature = "indexmap")]
1533impl<K: Decoder + Eq + std::hash::Hash, V: Decoder> Decoder for IndexMap<K, V> {
1534    fn decode(reader: &mut Bytes) -> Result<Self> {
1535        if reader.remaining() == 0 {
1536            return Err(EncoderError::InsufficientData);
1537        }
1538        let tag = reader.get_u8();
1539        if tag != TAG_MAP {
1540            return Err(EncoderError::Decode(format!(
1541                "Expected Map tag ({}), got {}",
1542                TAG_MAP, tag
1543            )));
1544        }
1545        let len = usize::decode(reader)?;
1546        let mut map = IndexMap::with_capacity(len);
1547        for _ in 0..len {
1548            let k = K::decode(reader)?;
1549            let v = V::decode(reader)?;
1550            map.insert(k, v);
1551        }
1552        Ok(map)
1553    }
1554}
1555
1556// --- DateTime<Utc> ---
1557/// Encodes a `chrono::DateTime<Utc>` as seconds and nanoseconds since the Unix epoch.
1558#[cfg(feature = "chrono")]
1559impl Encoder for DateTime<Utc> {
1560    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1561        writer.put_u8(TAG_CHRONO_DATETIME);
1562        let timestamp_seconds = self.timestamp();
1563        let timestamp_nanos = self.timestamp_subsec_nanos();
1564        timestamp_seconds.encode(writer)?;
1565        timestamp_nanos.encode(writer)?;
1566        Ok(())
1567    }
1568}
1569/// Decodes a `chrono::DateTime<Utc>` from the senax binary format.
1570#[cfg(feature = "chrono")]
1571impl Decoder for DateTime<Utc> {
1572    fn decode(reader: &mut Bytes) -> Result<Self> {
1573        if reader.remaining() == 0 {
1574            return Err(EncoderError::InsufficientData);
1575        }
1576        let tag = reader.get_u8();
1577        if tag != TAG_CHRONO_DATETIME {
1578            return Err(EncoderError::Decode(format!(
1579                "Expected DateTime<Utc> tag ({}), got {}",
1580                TAG_CHRONO_DATETIME, tag
1581            )));
1582        }
1583        let timestamp_seconds = i64::decode(reader)?;
1584        let timestamp_nanos = u32::decode(reader)?;
1585        DateTime::from_timestamp(timestamp_seconds, timestamp_nanos).ok_or_else(|| {
1586            EncoderError::Decode(format!(
1587                "Invalid timestamp: {} seconds, {} nanos",
1588                timestamp_seconds, timestamp_nanos
1589            ))
1590        })
1591    }
1592}
1593
1594// --- DateTime<Local> ---
1595#[cfg(feature = "chrono")]
1596impl Encoder for DateTime<Local> {
1597    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1598        writer.put_u8(TAG_CHRONO_DATETIME);
1599        let utc_dt = self.with_timezone(&Utc);
1600        let timestamp_seconds = utc_dt.timestamp();
1601        let timestamp_nanos = utc_dt.timestamp_subsec_nanos();
1602        timestamp_seconds.encode(writer)?;
1603        timestamp_nanos.encode(writer)?;
1604        Ok(())
1605    }
1606}
1607#[cfg(feature = "chrono")]
1608impl Decoder for DateTime<Local> {
1609    fn decode(reader: &mut Bytes) -> Result<Self> {
1610        if reader.remaining() == 0 {
1611            return Err(EncoderError::InsufficientData);
1612        }
1613        let tag = reader.get_u8();
1614        if tag != TAG_CHRONO_DATETIME {
1615            return Err(EncoderError::Decode(format!(
1616                "Expected DateTime<Local> tag ({}), got {}",
1617                TAG_CHRONO_DATETIME, tag
1618            )));
1619        }
1620        let timestamp_seconds = i64::decode(reader)?;
1621        let timestamp_nanos = u32::decode(reader)?;
1622        let utc_dt =
1623            DateTime::from_timestamp(timestamp_seconds, timestamp_nanos).ok_or_else(|| {
1624                EncoderError::Decode(format!(
1625                    "Invalid timestamp: {} seconds, {} nanos",
1626                    timestamp_seconds, timestamp_nanos
1627                ))
1628            })?;
1629        Ok(utc_dt.with_timezone(&Local))
1630    }
1631}
1632
1633// --- NaiveDate ---
1634#[cfg(feature = "chrono")]
1635impl Encoder for NaiveDate {
1636    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1637        writer.put_u8(TAG_CHRONO_NAIVE_DATE);
1638        // Store as days since 1970-01-01
1639        let days_from_epoch = self
1640            .signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap())
1641            .num_days();
1642        days_from_epoch.encode(writer)?;
1643        Ok(())
1644    }
1645}
1646#[cfg(feature = "chrono")]
1647impl Decoder for NaiveDate {
1648    fn decode(reader: &mut Bytes) -> Result<Self> {
1649        if reader.remaining() == 0 {
1650            return Err(EncoderError::InsufficientData);
1651        }
1652        let tag = reader.get_u8();
1653        if tag != TAG_CHRONO_NAIVE_DATE {
1654            return Err(EncoderError::Decode(format!(
1655                "Expected NaiveDate tag ({}), got {}",
1656                TAG_CHRONO_NAIVE_DATE, tag
1657            )));
1658        }
1659        let days_from_epoch = i64::decode(reader)?;
1660        let epoch_date = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1661        epoch_date
1662            .checked_add_signed(chrono::TimeDelta::try_days(days_from_epoch).unwrap())
1663            .ok_or_else(|| {
1664                EncoderError::Decode(format!("Invalid days from epoch: {}", days_from_epoch))
1665            })
1666    }
1667}
1668
1669// --- NaiveTime ---
1670#[cfg(feature = "chrono")]
1671impl Encoder for NaiveTime {
1672    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1673        writer.put_u8(TAG_CHRONO_NAIVE_TIME);
1674        // Store seconds and nanoseconds from 00:00:00 separately
1675        let seconds_from_midnight = self.num_seconds_from_midnight();
1676        let nanoseconds = self.nanosecond();
1677        seconds_from_midnight.encode(writer)?;
1678        nanoseconds.encode(writer)?;
1679        Ok(())
1680    }
1681}
1682#[cfg(feature = "chrono")]
1683impl Decoder for NaiveTime {
1684    fn decode(reader: &mut Bytes) -> Result<Self> {
1685        if reader.remaining() == 0 {
1686            return Err(EncoderError::InsufficientData);
1687        }
1688        let tag = reader.get_u8();
1689        if tag != TAG_CHRONO_NAIVE_TIME {
1690            return Err(EncoderError::Decode(format!(
1691                "Expected NaiveTime tag ({}), got {}",
1692                TAG_CHRONO_NAIVE_TIME, tag
1693            )));
1694        }
1695        let seconds_from_midnight = u32::decode(reader)?;
1696        let nanoseconds = u32::decode(reader)?;
1697        NaiveTime::from_num_seconds_from_midnight_opt(seconds_from_midnight, nanoseconds)
1698            .ok_or_else(|| {
1699                EncoderError::Decode(format!(
1700                    "Invalid seconds from midnight: {}, nanoseconds: {}",
1701                    seconds_from_midnight, nanoseconds
1702                ))
1703            })
1704    }
1705}
1706
1707// --- Bytes ---
1708impl Encoder for Bytes {
1709    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1710        writer.put_u8(TAG_BINARY);
1711        let len = self.len();
1712        len.encode(writer)?;
1713        writer.put_slice(self);
1714        Ok(())
1715    }
1716}
1717impl Decoder for Bytes {
1718    fn decode(reader: &mut Bytes) -> Result<Self> {
1719        if reader.remaining() == 0 {
1720            return Err(EncoderError::InsufficientData);
1721        }
1722        let tag = reader.get_u8();
1723        let len = if tag == TAG_BINARY {
1724            usize::decode(reader)?
1725        } else if (TAG_STRING_BASE..=TAG_STRING_LONG).contains(&tag) {
1726            if tag < TAG_STRING_LONG {
1727                (tag - TAG_STRING_BASE) as usize
1728            } else {
1729                usize::decode(reader)?
1730            }
1731        } else {
1732            return Err(EncoderError::Decode(format!(
1733                "Expected Bytes tag ({} or {}..={}), got {}",
1734                TAG_BINARY, TAG_STRING_BASE, TAG_STRING_LONG, tag
1735            )));
1736        };
1737
1738        if reader.remaining() < len {
1739            return Err(EncoderError::InsufficientData);
1740        }
1741
1742        Ok(reader.split_to(len))
1743    }
1744}
1745
1746// --- Decimal ---
1747#[cfg(feature = "rust_decimal")]
1748impl Encoder for Decimal {
1749    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1750        writer.put_u8(TAG_DECIMAL);
1751        // Get Decimal's internal representation and encode it
1752        let mantissa = self.mantissa();
1753        let scale = self.scale();
1754        mantissa.encode(writer)?;
1755        scale.encode(writer)?;
1756        Ok(())
1757    }
1758}
1759#[cfg(feature = "rust_decimal")]
1760impl Decoder for Decimal {
1761    fn decode(reader: &mut Bytes) -> Result<Self> {
1762        if reader.remaining() == 0 {
1763            return Err(EncoderError::InsufficientData);
1764        }
1765        let tag = reader.get_u8();
1766        if tag != TAG_DECIMAL {
1767            return Err(EncoderError::Decode(format!(
1768                "Expected Decimal tag ({}), got {}",
1769                TAG_DECIMAL, tag
1770            )));
1771        }
1772        let mantissa = i128::decode(reader)?;
1773        let scale = u32::decode(reader)?;
1774
1775        Decimal::try_from_i128_with_scale(mantissa, scale).map_err(|e| {
1776            EncoderError::Decode(format!(
1777                "Invalid decimal: mantissa={}, scale={}, error={}",
1778                mantissa, scale, e
1779            ))
1780        })
1781    }
1782}
1783
1784// --- UUID ---
1785#[cfg(feature = "uuid")]
1786impl Encoder for Uuid {
1787    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1788        writer.put_u8(TAG_UUID);
1789        // Write UUID as u128 little-endian in fixed 16 bytes
1790        let uuid_u128 = self.as_u128();
1791        writer.put_u128_le(uuid_u128);
1792        Ok(())
1793    }
1794}
1795#[cfg(feature = "uuid")]
1796impl Decoder for Uuid {
1797    fn decode(reader: &mut Bytes) -> Result<Self> {
1798        if reader.remaining() == 0 {
1799            return Err(EncoderError::InsufficientData);
1800        }
1801        let tag = reader.get_u8();
1802        if tag != TAG_UUID {
1803            return Err(EncoderError::Decode(format!(
1804                "Expected UUID tag ({}), got {}",
1805                TAG_UUID, tag
1806            )));
1807        }
1808        if reader.remaining() < 16 {
1809            return Err(EncoderError::InsufficientData);
1810        }
1811        let uuid_u128 = reader.get_u128_le();
1812        Ok(Uuid::from_u128(uuid_u128))
1813    }
1814}
1815
1816// --- ULID ---
1817#[cfg(feature = "ulid")]
1818impl Encoder for Ulid {
1819    fn encode(&self, writer: &mut BytesMut) -> Result<()> {
1820        writer.put_u8(TAG_UUID); // Use same tag as UUID
1821                                 // Write ULID as u128 little-endian in fixed 16 bytes
1822        let ulid_u128 = self.0;
1823        writer.put_u128_le(ulid_u128);
1824        Ok(())
1825    }
1826}
1827#[cfg(feature = "ulid")]
1828impl Decoder for Ulid {
1829    fn decode(reader: &mut Bytes) -> Result<Self> {
1830        if reader.remaining() == 0 {
1831            return Err(EncoderError::InsufficientData);
1832        }
1833        let tag = reader.get_u8();
1834        if tag != TAG_UUID {
1835            return Err(EncoderError::Decode(format!(
1836                "Expected ULID tag ({}), got {}",
1837                TAG_UUID, tag
1838            )));
1839        }
1840        if reader.remaining() < 16 {
1841            return Err(EncoderError::InsufficientData);
1842        }
1843        let ulid_u128 = reader.get_u128_le();
1844        Ok(Ulid(ulid_u128))
1845    }
1846}