commonware_codec/
extensions.rs

1//! Extension traits for ergonomic operations on encoding and decoding.
2//!
3//! These traits provide convenience methods (like `read()`, `decode()`, `read_range()`, and
4//! `decode_range()`) that simplify common use cases of the core [Read] and [Decode] traits,
5//! particularly when default configurations (`()`) or [RangeCfg] are involved.
6
7use crate::{Decode, Error, RangeCfg, Read};
8use bytes::Buf;
9
10/// Extension trait providing ergonomic read method for types requiring no configuration
11/// (i.e. `Cfg = ()`).
12///
13/// Import this trait to use the `.read(buf)` method as a shorthand for `.read_cfg(buf, ())`.
14pub trait ReadExt: Read<Cfg = ()> {
15    /// Reads a value using the default `()` config.
16    fn read(buf: &mut impl Buf) -> Result<Self, Error> {
17        Self::read_cfg(buf, &())
18    }
19}
20
21// Automatically implement `ReadExt` for types that implement `Read` with no config.
22impl<T: Read<Cfg = ()>> ReadExt for T {}
23
24/// Extension trait providing ergonomic decode method for types requiring no specific configuration.
25///
26/// Import this trait to use the `.decode(buf)` method as a shorthand for `.decode_cfg(buf, ())`.
27pub trait DecodeExt<X: Default>: Decode<Cfg = X> {
28    /// Decodes a value using the default `()` config.
29    fn decode(buf: impl Buf) -> Result<Self, Error> {
30        Self::decode_cfg(buf, &X::default())
31    }
32}
33
34// Automatically implement `DecodeExt` for types that implement `Decode` with no config.
35impl<X: Default, T: Decode<Cfg = X>> DecodeExt<X> for T {}
36
37/// Extension trait for reading types whose config is `(RangeCfg, X)` where `X` is [Default].
38///
39/// Useful for reading collections like [`Vec<T>`] where `T` implements [Read] with no specific
40/// configuration. Import this trait to use the `.read_range()` method.
41pub trait ReadRangeExt<X: Default>: Read<Cfg = (RangeCfg, X)> {
42    /// Reads a value using only a range configuration.
43    ///
44    /// The inner configuration type `X` must be [Default] and `X::default()` is used for it.
45    fn read_range(buf: &mut impl Buf, range: impl Into<RangeCfg>) -> Result<Self, Error> {
46        Self::read_cfg(buf, &(range.into(), X::default()))
47    }
48}
49
50// Automatically implement `ReadRangeExt` for types that implement `Read` with config
51// `(RangeCfg, X)`, where `X` is `Default`.
52impl<X: Default, U: Read<Cfg = (RangeCfg, X)>> ReadRangeExt<X> for U {}
53
54/// Extension trait for reading types whose config is `(RangeCfg, X)` where `X` is [Default],
55/// ensuring the buffer is consumed.
56///
57/// Useful for decoding collections like [`Vec<T>`] where `T` implements [Read] with no specific
58/// configuration. Import this trait to use the `.decode_range()` method.
59pub trait DecodeRangeExt<X: Default>: Decode<Cfg = (RangeCfg, X)> {
60    /// Decodes a value using only a range configuration.
61    ///
62    /// The inner configuration type `X` must be [Default] and `X::default()` is used for it.
63    fn decode_range(buf: impl Buf, range: impl Into<RangeCfg>) -> Result<Self, Error> {
64        Self::decode_cfg(buf, &(range.into(), X::default()))
65    }
66}
67
68// Automatically implement `DecodeRangeExt` for types that implement `Decode` with config
69// `(RangeCfg, X)`, where `X` has a default implementation.
70impl<X: Default, U: Decode<Cfg = (RangeCfg, X)>> DecodeRangeExt<X> for U {}