Skip to main content

osal_rs_serde/
ser.rs

1/***************************************************************************
2 *
3 * osal-rs-serde
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
18 *
19 ***************************************************************************/
20
21//! Serialization traits and implementations.
22//!
23//! This module provides the core serialization functionality for osal-rs-serde.
24//! It defines the [`Serialize`] trait for types that can be serialized and the
25//! [`Serializer`] trait for implementing custom serialization formats.
26//!
27//! # Overview
28//!
29//! - [`Serialize`]: Trait implemented by types that can be serialized
30//! - [`Serializer`]: Trait for implementing custom serialization formats  
31//! - [`ByteSerializer`]: Concrete implementation that writes little-endian binary data
32//!
33//! # Usage with Derive Macro
34//!
35//! The easiest way to implement serialization is using the derive macro:
36//!
37//! ```ignore
38//! use osal_rs_serde::Serialize;
39//!
40//! #[derive(Serialize)]
41//! struct SensorData {
42//!     temperature: i16,
43//!     humidity: u8,
44//!     pressure: u32,
45//! }
46//! ```
47//!
48//! # Manual Implementation
49//!
50//! For custom serialization logic, implement the trait manually:
51//!
52//! ```ignore
53//! use osal_rs_serde::{Serialize, Serializer};
54//!
55//! struct Point {
56//!     x: i32,
57//!     y: i32,
58//! }
59//!
60//! impl Serialize for Point {
61//!     fn serialize<S: Serializer>(&self, _name: &str, serializer: &mut S) -> Result<(), S::Error> {
62//!         serializer.serialize_i32("x", self.x)?;
63//!         serializer.serialize_i32("y", self.y)?;
64//!         Ok(())
65//!     }
66//! }
67//! ```
68//!
69//! # Supported Types
70//!
71//! The serialization framework supports:
72//! - All primitive types (bool, integers, floats)
73//! - Arrays `[T; N]` where T: Serialize
74//! - Tuples (up to 3 elements)
75//! - `Option<T>` where T: Serialize
76//! - `Vec<T>` where T: Serialize (requires `alloc`)
77//! - `String` and `&str` (requires `alloc` for String)
78//! - Custom types implementing `Serialize`
79
80#[cfg(feature = "alloc")]
81use alloc::string::String;
82
83use crate::error::{Error, Result};
84
85/// Trait for types that can be serialized.
86///
87/// This trait should be implemented (or derived) for any type that needs to be serialized.
88/// The implementation defines how the type should be written to a serializer.
89///
90/// # Derive Macro
91///
92/// The easiest way to implement this trait is using the derive macro (requires `derive` feature):
93///
94/// ```ignore
95/// use osal_rs_serde::Serialize;
96///
97/// #[derive(Serialize)]
98/// struct Config {
99///     id: u32,
100///     enabled: bool,
101///     timeout: Option<u16>,
102/// }
103/// ```
104///
105/// # Manual Implementation
106///
107/// For custom serialization logic or types not supported by the derive macro:
108///
109/// ```ignore
110/// use osal_rs_serde::{Serialize, Serializer};
111///
112/// struct Point {
113///     x: i32,
114///     y: i32,
115/// }
116///
117/// impl Serialize for Point {
118///     fn serialize<S: Serializer>(&self, serializer: &mut S) -> core::result::Result<(), S::Error> {
119///         serializer.serialize_i32("x", self.x)?;
120///         serializer.serialize_i32("y", self.y)?;
121///         Ok(())
122///     }
123/// }
124/// ```
125///
126/// # Built-in Implementations
127///
128/// This trait is already implemented for:
129/// - All primitive types (bool, u8-u128, i8-i128, f32, f64)
130/// - Arrays `[T; N]` where T: Serialize
131/// - Tuples (T1, T2) and (T1, T2, T3) where all T: Serialize
132/// - `Option<T>` where T: Serialize
133/// - `Vec<T>` where T: Serialize (requires `alloc`)
134/// - `String` and `&str` (requires `alloc` for String)
135pub trait Serialize {
136    /// Serialize this value using the given serializer.
137    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error>
138    where
139        S: Serializer;
140}
141
142/// Trait that defines how to serialize various types.
143///
144/// Implementations of this trait determine the output format.
145/// For example, `ByteSerializer` writes data in little-endian binary format.
146pub trait Serializer: Sized {
147    /// The error type that can be returned during serialization.
148    type Error: From<Error>;
149
150    /// Serialize a `bool` value.
151    fn serialize_bool(&mut self, name: &str, v: bool) -> core::result::Result<(), Self::Error>;
152
153    /// Serialize a `u8` value.
154    fn serialize_u8(&mut self, name: &str, v: u8) -> core::result::Result<(), Self::Error>;
155
156    /// Serialize an `i8` value.
157    fn serialize_i8(&mut self, name: &str, v: i8) -> core::result::Result<(), Self::Error>;
158
159    /// Serialize a `u16` value.
160    fn serialize_u16(&mut self, name: &str, v: u16) -> core::result::Result<(), Self::Error>;
161
162    /// Serialize an `i16` value.
163    fn serialize_i16(&mut self, name: &str, v: i16) -> core::result::Result<(), Self::Error>;
164
165    /// Serialize a `u32` value.
166    fn serialize_u32(&mut self, name: &str, v: u32) -> core::result::Result<(), Self::Error>;
167
168    /// Serialize an `i32` value.
169    fn serialize_i32(&mut self, name: &str, v: i32) -> core::result::Result<(), Self::Error>;
170
171    /// Serialize a `u64` value.
172    fn serialize_u64(&mut self, name: &str, v: u64) -> core::result::Result<(), Self::Error>;
173
174    /// Serialize an `i64` value.
175    fn serialize_i64(&mut self, name: &str, v: i64) -> core::result::Result<(), Self::Error>;
176
177    /// Serialize a `u128` value.
178    fn serialize_u128(&mut self, name: &str, v: u128) -> core::result::Result<(), Self::Error>;
179
180    /// Serialize an `i128` value.
181    fn serialize_i128(&mut self, name: &str, v: i128) -> core::result::Result<(), Self::Error>;
182
183    /// Serialize an `f32` value.
184    fn serialize_f32(&mut self, name: &str, v: f32) -> core::result::Result<(), Self::Error>;
185
186    /// Serialize an `f64` value.
187    fn serialize_f64(&mut self, name: &str, v: f64) -> core::result::Result<(), Self::Error>;
188
189    /// Serialize a byte slice.
190    fn serialize_bytes(&mut self, name: &str, v: &[u8]) -> core::result::Result<(), Self::Error>;
191
192    /// Serialize a string.
193    fn serialize_string(&mut self, name: &str, v: &String) -> core::result::Result<(), Self::Error>;
194
195    /// Serialize a string slice.
196    fn serialize_str(&mut self, name: &str, v: &str) -> core::result::Result<(), Self::Error>;
197
198    /// Serialize a vector of serializable items.
199    fn serialize_vec<T>(&mut self, name: &str, v: &alloc::vec::Vec<T>) -> core::result::Result<(), Self::Error>
200    where
201        T: Serialize;
202
203    /// Serialize an array of serializable items.
204    fn serialize_array<T>(&mut self, name: &str, v: &[T]) -> core::result::Result<(), Self::Error>
205    where
206        T: Serialize;
207
208    /// Begin serializing a struct with the given name and number of fields.
209    /// Default implementation does nothing (suitable for binary formats).
210    fn serialize_struct_start(&mut self, _name: &str, _len: usize) -> core::result::Result<(), Self::Error> {
211        Ok(())
212    }
213
214    /// Serialize a struct field with name and value.
215    /// Default implementation just serializes the value.
216    fn serialize_field<T>(&mut self, name: &str, value: &T) -> core::result::Result<(), Self::Error>
217    where
218        T: Serialize,
219    {
220        value.serialize(name, self)
221    }
222
223    /// End serializing a struct.
224    /// Default implementation does nothing (suitable for binary formats).
225    fn serialize_struct_end(&mut self) -> core::result::Result<(), Self::Error> {
226        Ok(())
227    }
228}
229
230/// A serializer that writes data to a byte buffer in little-endian format.
231///
232/// This is a concrete implementation of the `Serializer` trait that writes
233/// binary data in a compact, little-endian format. This is the default serializer
234/// used by the [`crate::to_bytes`] convenience function.
235///
236/// # Format
237///
238/// - All integers are written in little-endian byte order
239/// - Floating-point numbers use IEEE 754 representation
240/// - `bool` is written as a single byte (0 or 1)
241/// - `Option<T>`: 1 byte tag (0=None, 1=Some) followed by T if Some
242/// - Arrays: Elements serialized sequentially (no length prefix)
243/// - Tuples: Elements serialized sequentially
244/// - Strings/Vec: u32 length prefix followed by data
245///
246/// # Examples
247///
248/// ## Basic Usage
249///
250/// ```ignore
251/// use osal_rs_serde::{ByteSerializer, Serializer, Serialize};
252///
253/// let mut buffer = [0u8; 16];
254/// let mut serializer = ByteSerializer::new(&mut buffer);
255///
256/// serializer.serialize_u32("", 42).unwrap();
257/// serializer.serialize_bool("", true).unwrap();
258/// serializer.serialize_i16("", -100).unwrap();
259///
260/// let len = serializer.position();
261/// println!("Serialized {} bytes", len);
262/// ```
263///
264/// ## With Structs
265///
266/// ```ignore
267/// use osal_rs_serde::{ByteSerializer, Serialize};
268///
269/// #[derive(Serialize)]
270/// struct Message {
271///     id: u32,
272///     value: i16,
273/// }
274///
275/// let msg = Message { id: 100, value: -50 };
276/// let mut buffer = [0u8; 32];
277/// let mut serializer = ByteSerializer::new(&mut buffer);
278/// msg.serialize(&mut serializer).unwrap();
279/// ```
280///
281/// # Memory Layout
282///
283/// The serializer writes data sequentially without padding or alignment:
284///
285/// ```text
286/// struct Data { a: u16, b: u32 }
287/// Memory: [a_lo, a_hi, b0, b1, b2, b3]
288/// ```
289pub struct ByteSerializer<'a> {
290    buffer: &'a mut [u8],
291    position: usize,
292}
293
294impl<'a> ByteSerializer<'a> {
295    /// Create a new ByteSerializer with the given buffer.
296    pub fn new(buffer: &'a mut [u8]) -> Self {
297        Self {
298            buffer,
299            position: 0,
300        }
301    }
302
303    /// Get the current position in the buffer.
304    pub fn position(&self) -> usize {
305        self.position
306    }
307
308    /// Write bytes to the buffer.
309    fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
310        if self.position + bytes.len() > self.buffer.len() {
311            return Err(Error::BufferTooSmall);
312        }
313        self.buffer[self.position..self.position + bytes.len()].copy_from_slice(bytes);
314        self.position += bytes.len();
315        Ok(())
316    }
317}
318
319impl<'a> Serializer for ByteSerializer<'a> {
320    type Error = Error;
321
322    fn serialize_bool(&mut self, _name: &str, v: bool) -> Result<()> {
323        self.serialize_u8("", if v { 1 } else { 0 })
324    }
325
326    fn serialize_u8(&mut self, _name: &str, v: u8) -> Result<()> {
327        self.write_bytes(&[v])
328    }
329
330    fn serialize_i8(&mut self, _name: &str, v: i8) -> Result<()> {
331        self.write_bytes(&v.to_le_bytes())
332    }
333
334    fn serialize_u16(&mut self, _name: &str, v: u16) -> Result<()> {
335        self.write_bytes(&v.to_le_bytes())
336    }
337
338    fn serialize_i16(&mut self, _name: &str, v: i16) -> Result<()> {
339        self.write_bytes(&v.to_le_bytes())
340    }
341
342    fn serialize_u32(&mut self, _name: &str, v: u32) -> Result<()> {
343        self.write_bytes(&v.to_le_bytes())
344    }
345
346    fn serialize_i32(&mut self, _name: &str, v: i32) -> Result<()> {
347        self.write_bytes(&v.to_le_bytes())
348    }
349
350    fn serialize_u64(&mut self, _name: &str, v: u64) -> Result<()> {
351        self.write_bytes(&v.to_le_bytes())
352    }
353
354    fn serialize_i64(&mut self, _name: &str, v: i64) -> Result<()> {
355        self.write_bytes(&v.to_le_bytes())
356    }
357
358    fn serialize_u128(&mut self, _name: &str, v: u128) -> Result<()> {
359        self.write_bytes(&v.to_le_bytes())
360    }
361
362    fn serialize_i128(&mut self, _name: &str, v: i128) -> Result<()> {
363        self.write_bytes(&v.to_le_bytes())
364    }
365
366    fn serialize_f32(&mut self, _name: &str, v: f32) -> Result<()> {
367        self.write_bytes(&v.to_le_bytes())
368    }
369
370    fn serialize_f64(&mut self, _name: &str, v: f64) -> Result<()> {
371        self.write_bytes(&v.to_le_bytes())
372    }
373
374    fn serialize_bytes(&mut self, _name: &str, v: &[u8]) -> Result<()> {
375        // First write the length as u32
376        self.serialize_u32("", v.len() as u32)?;
377        self.write_bytes(v)
378    }
379
380    fn serialize_string(&mut self, name: &str, v: &String) -> core::result::Result<(), Self::Error> {
381        self.serialize_str(name, v.as_str())
382    }
383
384    fn serialize_str(&mut self, name: &str, v: &str) -> core::result::Result<(), Self::Error> {
385        self.serialize_bytes(name, v.as_bytes())
386    }
387
388    fn serialize_vec<T>(&mut self, name: &str, v: &alloc::vec::Vec<T>) -> core::result::Result<(), Self::Error> 
389    where
390        T: Serialize {
391        // First write the length as u32
392        self.serialize_u32(name, v.len() as u32)?;
393        for item in v.iter() {
394            item.serialize(name, self)?;
395        }
396        Ok(())
397    }
398
399    /// Serialize an array of serializable items.
400    fn serialize_array<T>(&mut self, name: &str, v: &[T]) -> core::result::Result<(), Self::Error> 
401    where
402        T: Serialize {
403        for item in v.iter() {
404            item.serialize(name, self)?;
405        }
406        Ok(())
407    }
408
409}
410
411// Implementations for primitive types
412
413impl Serialize for bool {
414    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
415    where
416        S: Serializer
417    {
418    
419        serializer.serialize_bool(name, *self)
420    }
421}
422
423impl Serialize for u8 {
424    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
425    where
426        S: Serializer,
427    {
428        serializer.serialize_u8(name, *self)
429    }
430}
431
432impl Serialize for i8 {
433    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
434    where
435        S: Serializer,
436    {
437        serializer.serialize_i8(name, *self)
438    }
439}
440
441impl Serialize for u16 {
442    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
443    where
444        S: Serializer,
445    {
446        serializer.serialize_u16(name, *self)
447    }
448}
449
450impl Serialize for i16 {
451    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
452    where
453        S: Serializer,
454    {
455        serializer.serialize_i16(name, *self)
456    }
457}
458
459impl Serialize for u32 {
460    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
461    where
462        S: Serializer,
463    {
464        serializer.serialize_u32(name, *self)
465    }
466}
467
468impl Serialize for i32 {
469    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
470    where
471        S: Serializer,
472    {
473        serializer.serialize_i32(name, *self)
474    }
475}
476
477impl Serialize for u64 {
478    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
479    where
480        S: Serializer,
481    {
482        serializer.serialize_u64(name, *self)
483    }
484}
485
486impl Serialize for i64 {
487    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
488    where
489        S: Serializer,
490    {
491        serializer.serialize_i64(name, *self)
492    }
493}
494
495impl Serialize for u128 {
496    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
497    where
498        S: Serializer,
499    {
500        serializer.serialize_u128(name, *self)
501    }
502}
503
504impl Serialize for i128 {
505    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
506    where
507        S: Serializer,
508    {
509        serializer.serialize_i128(name, *self)
510    }
511}
512
513impl Serialize for f32 {
514    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
515    where
516        S: Serializer,
517    {
518        serializer.serialize_f32(name, *self)
519    }
520}
521
522impl Serialize for f64 {
523    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
524    where
525        S: Serializer,
526    {
527        serializer.serialize_f64(name, *self)
528    }
529}
530
531// String implementations
532impl Serialize for &str {
533    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
534    where
535        S: Serializer,
536    {
537        serializer.serialize_str(name, self)
538    }
539}
540
541#[cfg(feature = "alloc")]
542impl Serialize for String {
543    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
544    where
545        S: Serializer,
546    {
547        serializer.serialize_string(name, self)
548    }
549}
550
551// Array implementation
552impl<T: Serialize, const N: usize> Serialize for [T; N] {
553    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
554    where
555        S: Serializer
556    {
557        serializer.serialize_array(name, self)
558    }
559}
560
561// Tuple implementations
562impl<T1: Serialize, T2: Serialize> Serialize for (T1, T2) {
563    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
564    where
565        S: Serializer,
566    {
567        self.0.serialize(name, serializer)?;
568        self.1.serialize(name, serializer)?;
569        Ok(())
570    }
571}
572
573impl<T1: Serialize, T2: Serialize, T3: Serialize> Serialize for (T1, T2, T3) {
574    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
575    where
576        S: Serializer
577    {
578        self.0.serialize(name, serializer)?;
579        self.1.serialize(name, serializer)?;
580        self.2.serialize(name, serializer)?;
581        Ok(())
582    }
583}
584
585// Option implementation
586impl<T: Serialize> Serialize for Option<T> {
587    fn serialize<S>(&self, name: &str, serializer: &mut S) -> core::result::Result<(), S::Error> 
588    where
589        S: Serializer,
590    {
591        match self {
592            Some(value) => {
593                serializer.serialize_u8(name, 1)?;
594                value.serialize(name, serializer)?;
595            }
596            None => {
597                serializer.serialize_u8(name, 0)?;
598            }
599        }
600        Ok(())
601    }
602}