compio_io/framed/
mod.rs

1//! Framed I/O operations.
2//!
3//! This module provides functionality for encoding and decoding frames
4//! for network protocols and other stream-based communication.
5
6use std::marker::PhantomData;
7
8use futures_util::FutureExt;
9
10use crate::{AsyncRead, buffer::Buffer, framed::codec::Decoder, util::Splittable};
11
12pub mod codec;
13pub mod frame;
14
15mod read;
16mod write;
17
18/// A framed encoder/decoder that handles both [`Sink`] for writing frames and
19/// [`Stream`] for reading frames.
20///
21/// It uses a [`codec`] to encode/decode messages into frames (`T -> Vec<u8>`)
22/// and a [`Framer`] to define how frames are laid out in buffer (`&mut [u8] ->
23/// &mut [u8]`).
24pub struct Framed<R, W, C, F, In, Out> {
25    read_state: read::State<R>,
26    write_state: write::State<W>,
27    codec: C,
28    framer: F,
29    types: PhantomData<(In, Out)>,
30}
31
32/// [`Framed`] with same In ([`Sink`]) and Out ([`Stream::Item`]) type
33pub type SymmetricFramed<R, W, C, F, Item> = Framed<R, W, C, F, Item, Item>;
34
35impl<R, W, C, F, In, Out> Framed<R, W, C, F, In, Out> {
36    /// Change the reader of the `Framed` object.
37    pub fn with_reader<Io>(self, reader: Io) -> Framed<Io, W, C, F, In, Out> {
38        Framed {
39            read_state: read::State::Idle(Some((reader, Buffer::with_capacity(64)))),
40            write_state: self.write_state,
41            codec: self.codec,
42            framer: self.framer,
43            types: PhantomData,
44        }
45    }
46
47    /// Change the writer of the `Framed` object.
48    pub fn with_writer<Io>(self, writer: Io) -> Framed<R, Io, C, F, In, Out> {
49        Framed {
50            read_state: self.read_state,
51            write_state: write::State::Idle(Some((writer, Vec::new()))),
52            codec: self.codec,
53            framer: self.framer,
54            types: PhantomData,
55        }
56    }
57
58    /// Change the codec of the `Framed` object.
59    ///
60    /// This is useful when you have a duplex I/O type, e.g., a `TcpStream` or
61    /// `File`, and you want [`Framed`] to implement both
62    /// [`Sink`](futures_util::Sink) and [`Stream`](futures_util::Stream).
63    pub fn with_duplex<Io: Splittable>(
64        self,
65        io: Io,
66    ) -> Framed<Io::ReadHalf, Io::WriteHalf, C, F, In, Out> {
67        let (read_half, write_half) = io.split();
68
69        Framed {
70            read_state: read::State::Idle(Some((read_half, Buffer::with_capacity(64)))),
71            write_state: write::State::Idle(Some((write_half, Vec::new()))),
72            codec: self.codec,
73            framer: self.framer,
74            types: PhantomData,
75        }
76    }
77}
78
79impl<C, F> Framed<(), (), C, F, (), ()> {
80    /// Creates a new `Framed` with the given I/O object, codec, framer and a
81    /// different input and output type.
82    pub fn new<In, Out>(codec: C, framer: F) -> Framed<(), (), C, F, In, Out> {
83        Framed {
84            read_state: read::State::Idle(None),
85            write_state: write::State::Idle(None),
86            codec,
87            framer,
88            types: PhantomData,
89        }
90    }
91
92    /// Creates a new `Framed` with the given I/O object, codec, and framer with
93    /// the same input and output type.
94    pub fn symmetric<T>(codec: C, framer: F) -> Framed<(), (), C, F, T, T> {
95        Framed {
96            read_state: read::State::Idle(None),
97            write_state: write::State::Idle(None),
98            codec,
99            framer,
100            types: PhantomData,
101        }
102    }
103}