dencode/
sink.rs

1/// An `IterSink` is a value into which other values can be sent.
2///
3/// Values are sent in two phases: first by internally buffering the value,
4/// and then actually writing the value upon flushing.
5pub trait IterSink<Item> {
6    /// The type of value produced by the sink when an error occurs.
7    type Error;
8
9    /// Attempts to prepare the `IterSink` to receive a value, adjusting the internal
10    /// buffer if necessary.
11    ///
12    /// This method must be called prior to each call to `start_send`.
13    fn ready(&mut self) -> Result<(), Self::Error>;
14
15    /// Write a value to the internal buffer.
16    /// Each call to this function must be preceded by a successful call to `ready`.
17    fn start_send(&mut self, item: Item) -> Result<(), Self::Error>;
18
19    /// Flush any remaining output from this sink's internal buffer.
20    fn flush(&mut self) -> Result<(), Self::Error>;
21}
22
23/// An extension trait for `IterSink`s that provides a few convenient functions.
24pub trait IterSinkExt<Item>: IterSink<Item> {
25    /// Fully processed an item into the sink, including flushing.
26    ///
27    /// Note that, because of the flushing requirement, it is usually better to batch
28    /// together items to send via send_all, rather than flushing between each item.
29    fn send(&mut self, item: Item) -> Result<(), Self::Error> {
30        self.send_all(std::iter::once(Ok(item)))
31    }
32
33    /// Fully process the iterator of items into the sink, including flushing.
34    ///
35    /// This will drive the iterator to keep producing items until it is exhausted, sending each item to the sink.
36    /// It will complete once both the input iterator is exhausted, and the sink has
37    /// received and flushed all items.
38    fn send_all<I>(&mut self, items: I) -> Result<(), Self::Error>
39    where
40        I: IntoIterator<Item = Result<Item, Self::Error>>,
41    {
42        for item in items {
43            let item = item?;
44            self.ready()?;
45            self.start_send(item)?;
46        }
47        self.flush()
48    }
49}
50
51impl<T: ?Sized, Item> IterSinkExt<Item> for T where T: IterSink<Item> {}