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 [`RangeConfig`] are involved.
6
7use crate::{Config, Decode, Error, RangeConfig, 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<()> {
15 /// Reads a value using the default `()` config.
16 fn read(buf: &mut impl Buf) -> Result<Self, Error> {
17 <Self as Read<()>>::read_cfg(buf, &())
18 }
19}
20
21// Automatically implement `ReadExt` for types that implement `Read` with no config.
22impl<T: Read<()>> ReadExt for T {}
23
24/// Extension trait providing ergonomic decode method for types requiring no configuration
25/// (i.e. `Cfg = ()`).
26///
27/// Import this trait to use the `.decode(buf)` method as a shorthand for `.decode_cfg(buf, ())`.
28pub trait DecodeExt: Decode<()> {
29 /// Decodes a value using the default `()` config.
30 fn decode(buf: impl Buf) -> Result<Self, Error> {
31 <Self as Decode<()>>::decode_cfg(buf, &())
32 }
33}
34
35// Automatically implement `DecodeExt` for types that implement `Decode` with no config.
36impl<T: Decode<()>> DecodeExt for T {}
37
38/// Extension trait for reading types whose config is `(RangeConfig, T)` where `T` is a unit type
39/// (a type of one possible value, such as `()` or `((), ())`).
40///
41/// Useful for reading collections like `Vec<T>` where `T` implements `Read<()>`.
42/// Import this trait to use the `.read_range()` method.
43pub trait ReadRangeExt<T: Config + Default, R: RangeConfig>: Read<(R, T)> {
44 /// Reads a value using only a range configuration.
45 /// Assumes the inner configuration is a unit type.
46 fn read_range(buf: &mut impl Buf, range: R) -> Result<Self, Error> {
47 Self::read_cfg(buf, &(range, T::default()))
48 }
49}
50
51// Blanket implementation ONLY for T = ()
52// Applies to types like Vec<U> where U: Read<()>
53impl<R: RangeConfig, U: Read<(R, ())>> ReadRangeExt<(), R> for U {}
54
55// Blanket implementation ONLY for T = ((), ())
56// Applies to types like HashMap<K, V> where K: Read<()>, V: Read<()>
57impl<R: RangeConfig, U: Read<(R, ((), ()))>> ReadRangeExt<((), ()), R> for U {}
58
59/// Extension trait for decoding types whose config is `(RangeConfig, T)`,
60/// i.e., requiring a range but no specific inner configuration, ensuring the buffer is consumed.
61///
62/// Useful for decoding collections like `Vec<T>` where `T` implements `Read<()>`.
63/// Import this trait to use the `.decode_range()` method.
64pub trait DecodeRangeExt<T: Config + Default, R: RangeConfig>: Decode<(R, T)> {
65 fn decode_range(buf: impl Buf, range: R) -> Result<Self, Error> {
66 Self::decode_cfg(buf, &(range, T::default()))
67 }
68}
69
70// Blanket implementation ONLY for T = ()
71impl<R: RangeConfig, U: Decode<(R, ())>> DecodeRangeExt<(), R> for U {}
72
73// Blanket implementation ONLY for T = ((), ())
74impl<R: RangeConfig, U: Decode<(R, ((), ()))>> DecodeRangeExt<((), ()), R> for U {}