diny_core/backend/
encode.rs

1use core::task::{Context, Poll};
2use crate::backend::{Format, FormatEncode};
3use crate::io;
4
5
6/// Contains the resultant state of a [start_encode](Encode) opertation.
7///
8/// This is very simlar to the [Poll] enum, except that it is flattened
9/// and that in the event that the operation is pending, the [encode](Encode)
10/// state required to resume the operation is returned.
11pub enum StartEncodeStatus<Enc, Err> {
12    Fini,
13    Pending(Enc),
14    Error(Err),
15}
16
17impl<Enc, Err> StartEncodeStatus<Enc, Err> {
18    #[inline(always)]
19    pub fn map_pending<F, E>(self, f: F) -> StartEncodeStatus<E, Err>
20    where
21        F: FnOnce(Enc) -> E,
22    {
23        match self {
24            Self::Fini         => StartEncodeStatus::Fini,
25            Self::Pending(enc) => StartEncodeStatus::Pending(f(enc)),
26            Self::Error(e)     => StartEncodeStatus::Error(e),
27        }
28    }
29}
30
31/// Contains the resultant state of a [poll_encode](Encode) opertation.
32///
33/// This is very simlar to the [Poll] enum, except that it is flattened.
34pub enum PollEncodeStatus<Err> {
35    Fini,
36    Pending,
37    Error(Err),
38}
39
40impl<Err> PollEncodeStatus<Err> {
41    #[inline(always)]
42    pub fn lift<Enc>(self, enc: Enc) -> StartEncodeStatus<Enc, Err> {
43        match self {
44            PollEncodeStatus::Fini       => StartEncodeStatus::Fini,
45            PollEncodeStatus::Pending    => StartEncodeStatus::Pending(enc),
46            PollEncodeStatus::Error(err) => StartEncodeStatus::Error(err),
47        }
48    }
49
50    #[inline(always)]
51    pub fn map_err<F, E>(self, f: F) -> PollEncodeStatus<E>
52    where
53        F: FnOnce(Err) -> E,
54    {
55        match self {
56            PollEncodeStatus::Fini => PollEncodeStatus::Fini,
57            PollEncodeStatus::Pending => PollEncodeStatus::Pending,
58            PollEncodeStatus::Error(err) => PollEncodeStatus::Error(f(err))
59        }
60    }
61}
62
63impl<Err> From<PollEncodeStatus<Err>> for Poll<Result<(), Err>> {
64    #[inline(always)]
65    fn from(status: PollEncodeStatus<Err>) -> Self {
66        match status {
67            PollEncodeStatus::Fini     => Poll::Ready(Ok(())),
68            PollEncodeStatus::Pending  => Poll::Pending,
69            PollEncodeStatus::Error(e) => Poll::Ready(Err(e)),
70        }
71    }
72}
73
74/// Attempt to encode a data structure to an [asynchronous writer](io::AsyncWrite)
75/// for a particular [format](FormatEncode).
76pub trait Encode: Sized {
77    /// The concrete [format](FormatEncode) to encode with.
78    type Format: FormatEncode;
79    
80    /// The concrete data structure to encode.
81    type Data: ?Sized;
82
83    /// Initialize the internal state of the encoder.
84    fn init(data: &Self::Data) -> Self;
85
86    /// Begin encoding bytes for the indicated [format](FormatEncode) to the provided [writer](io::AsyncWrite).
87    ///
88    /// This is intended to be overriden whenever an optimized code path exists for the (usual) case where
89    /// enough buffer space is available that the operation will succeed immediately without [pending](Poll).
90    ///
91    /// # Implementation
92    /// Implementions must ensure that `start_encode` is semantically equivalent to calling
93    /// `init` followed by `poll_encode`
94    fn start_encode<W>(format: &Self::Format, writer: &mut W, data: &Self::Data, cx: &mut Context<'_>) -> StartEncodeStatus<Self, <<Self as Encode>::Format as Format>::Error>
95    where
96        W: io::AsyncWrite + Unpin,
97    {
98        let mut enc = Self::init(data);
99        enc.poll_encode(format, writer, data, cx)
100        .lift(enc)
101    }
102
103    /// Continue a [pending](Poll) [Encode] operation.
104    fn poll_encode<W>(&mut self, format: &Self::Format, writer: &mut W, data: &Self::Data, cx: &mut Context<'_>) -> PollEncodeStatus<<<Self as Encode>::Format as Format>::Error>
105    where
106        W: io::AsyncWrite + Unpin,
107    ;
108}
109
110
111
112
113