Skip to main content

pamoja_codec/
lib.rs

1//! Pluggable serialization for pamoja payloads.
2//!
3//! Concrete wire formats - CBOR for constrained devices, Protocol Buffers, JSON,
4//! or raw framing - implement the [`Codec`] trait. This crate defines the trait
5//! and provides serde-based implementations behind feature flags:
6//!
7//! - [`CborCodec`] (feature `cbor`, on by default) - compact binary framing for
8//!   constrained devices and metered links.
9//! - [`JsonCodec`] (feature `json`, on by default) - human-readable framing for
10//!   interop and debugging.
11//! - [`BytesCodec`] (always available) - a no-op codec that carries raw bytes.
12//!
13//! For metered links it also packs batches of samples into far fewer bytes:
14//! [`encode_deltas`] delta-encodes a series of integers, and [`Quantizer`] rounds
15//! `f32` readings to a fixed precision and delta-encodes them.
16//!
17//! # Examples
18//!
19//! A little-endian codec for `u32` values:
20//!
21//! ```
22//! use pamoja_codec::Codec;
23//! use pamoja_core::{Error, Result};
24//!
25//! struct LeU32;
26//!
27//! impl Codec<u32> for LeU32 {
28//!     fn encode(&self, value: &u32) -> Result<Vec<u8>> {
29//!         Ok(value.to_le_bytes().to_vec())
30//!     }
31//!
32//!     fn decode(&self, bytes: &[u8]) -> Result<u32> {
33//!         let array = bytes
34//!             .try_into()
35//!             .map_err(|_| Error::Codec("expected 4 bytes".into()))?;
36//!         Ok(u32::from_le_bytes(array))
37//!     }
38//! }
39//!
40//! let codec = LeU32;
41//! let encoded = codec.encode(&42).unwrap();
42//! assert_eq!(codec.decode(&encoded).unwrap(), 42);
43//! ```
44
45use pamoja_core::Result;
46
47mod bytes;
48pub use bytes::BytesCodec;
49
50mod delta;
51pub use delta::{decode_deltas, encode_deltas, Quantizer};
52
53#[cfg(feature = "cbor")]
54mod cbor;
55#[cfg(feature = "cbor")]
56pub use cbor::CborCodec;
57
58#[cfg(feature = "json")]
59mod json;
60#[cfg(feature = "json")]
61pub use json::JsonCodec;
62
63/// Encodes and decodes values of type `T` to and from byte buffers.
64///
65/// A codec is the bridge between in-memory values and the bytes carried by a
66/// [`Transport`](pamoja_core::Transport) or persisted by a
67/// [`Store`](pamoja_core::Store).
68pub trait Codec<T> {
69    /// Encodes a value into a byte buffer.
70    ///
71    /// # Arguments
72    ///
73    /// * `value` - the value to serialize.
74    ///
75    /// # Returns
76    ///
77    /// A byte buffer containing the encoded representation of `value`.
78    ///
79    /// # Errors
80    ///
81    /// Returns [`Error::Codec`](pamoja_core::Error::Codec) if the value cannot
82    /// be encoded.
83    fn encode(&self, value: &T) -> Result<Vec<u8>>;
84
85    /// Decodes a value from a byte buffer.
86    ///
87    /// # Arguments
88    ///
89    /// * `bytes` - the encoded representation to deserialize.
90    ///
91    /// # Returns
92    ///
93    /// The value decoded from `bytes`.
94    ///
95    /// # Errors
96    ///
97    /// Returns [`Error::Codec`](pamoja_core::Error::Codec) if `bytes` is not a
98    /// valid encoding of `T`.
99    fn decode(&self, bytes: &[u8]) -> Result<T>;
100}