storey_encoding/
lib.rs

1pub trait Encoding {
2    /// The error type returned when encoding fails.
3    type EncodeError: std::fmt::Display;
4
5    /// The error type returned when decoding fails.
6    type DecodeError: std::fmt::Display;
7}
8
9pub trait EncodableWith<E: Encoding>: sealed::SealedE<E> {
10    fn encode(&self) -> Result<Vec<u8>, E::EncodeError>;
11}
12
13pub trait EncodableWithImpl<E: Encoding> {
14    fn encode_impl(self) -> Result<Vec<u8>, E::EncodeError>;
15}
16
17impl<E: Encoding, T> EncodableWith<E> for T
18where
19    for<'a> Cover<&'a T>: EncodableWithImpl<E>,
20{
21    fn encode(&self) -> Result<Vec<u8>, <E as Encoding>::EncodeError> {
22        Cover(self).encode_impl()
23    }
24}
25
26pub trait DecodableWith<E: Encoding>: Sized + sealed::SealedD<E> {
27    fn decode(data: &[u8]) -> Result<Self, E::DecodeError>;
28}
29
30pub trait DecodableWithImpl<E: Encoding>: Sized {
31    fn decode_impl(data: &[u8]) -> Result<Self, E::DecodeError>;
32}
33
34impl<E: Encoding, T> DecodableWith<E> for T
35where
36    Cover<T>: DecodableWithImpl<E>,
37{
38    fn decode(data: &[u8]) -> Result<Self, <E as Encoding>::DecodeError> {
39        let wrapper = <Cover<Self>>::decode_impl(data)?;
40        Ok(wrapper.0)
41    }
42}
43
44mod sealed {
45    // This module is private to the crate. It's used to seal the `EncodableWith` and
46    // `DecodableWith` traits, so that the only way they can be implemented outside
47    // this crate is through the blanket implementations provided by `EncodableWithImpl`
48    // and `DecodableWithImpl`.
49    //
50    // More information on sealed traits:
51    // https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
52
53    use super::*;
54
55    pub trait SealedE<E> {}
56    pub trait SealedD<E> {}
57
58    impl<E: Encoding, T> SealedE<E> for T where for<'a> Cover<&'a T>: EncodableWithImpl<E> {}
59    impl<E: Encoding, T> SealedD<E> for T where Cover<T>: DecodableWithImpl<E> {}
60}
61
62pub struct Cover<T>(pub T);