storey_encoding/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
pub trait Encoding {
    /// The error type returned when encoding fails.
    type EncodeError;

    /// The error type returned when decoding fails.
    type DecodeError;
}

pub trait EncodableWith<E: Encoding>: sealed::SealedE<E> {
    fn encode(&self) -> Result<Vec<u8>, E::EncodeError>;
}

pub trait EncodableWithImpl<E: Encoding> {
    fn encode_impl(self) -> Result<Vec<u8>, E::EncodeError>;
}

impl<E: Encoding, T> EncodableWith<E> for T
where
    for<'a> Cover<&'a T>: EncodableWithImpl<E>,
{
    fn encode(&self) -> Result<Vec<u8>, <E as Encoding>::EncodeError> {
        Cover(self).encode_impl()
    }
}

pub trait DecodableWith<E: Encoding>: Sized + sealed::SealedD<E> {
    fn decode(data: &[u8]) -> Result<Self, E::DecodeError>;
}

pub trait DecodableWithImpl<E: Encoding>: Sized {
    fn decode_impl(data: &[u8]) -> Result<Self, E::DecodeError>;
}

impl<E: Encoding, T> DecodableWith<E> for T
where
    Cover<T>: DecodableWithImpl<E>,
{
    fn decode(data: &[u8]) -> Result<Self, <E as Encoding>::DecodeError> {
        let wrapper = <Cover<Self>>::decode_impl(data)?;
        Ok(wrapper.0)
    }
}

mod sealed {
    // This module is private to the crate. It's used to seal the `EncodableWith` and
    // `DecodableWith` traits, so that the only way they can be implemented outside
    // this crate is through the blanket implementations provided by `EncodableWithImpl`
    // and `DecodableWithImpl`.
    //
    // More information on sealed traits:
    // https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed

    use super::*;

    pub trait SealedE<E> {}
    pub trait SealedD<E> {}

    impl<E: Encoding, T> SealedE<E> for T where for<'a> Cover<&'a T>: EncodableWithImpl<E> {}
    impl<E: Encoding, T> SealedD<E> for T where Cover<T>: DecodableWithImpl<E> {}
}

pub struct Cover<T>(pub T);