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]`).
24///
25/// [`Framer`]: frame::Framer
26/// [`Sink`]: futures_util::Sink
27/// [`Stream`]: futures_util::Stream
28pub struct Framed<R, W, C, F, In, Out> {
29    read_state: read::State<R>,
30    write_state: write::State<W>,
31    codec: C,
32    framer: F,
33    types: PhantomData<(In, Out)>,
34}
35
36/// [`Framed`] with same In ([`Sink`]) and Out ([`Stream::Item`]) type
37///
38/// [`Sink`]: futures_util::Sink
39/// [`Stream::Item`]: futures_util::Stream::Item
40pub type SymmetricFramed<R, W, C, F, Item> = Framed<R, W, C, F, Item, Item>;
41
42impl<R, W, C, F, In, Out> Framed<R, W, C, F, In, Out> {
43    /// Change the reader of the `Framed` object.
44    pub fn with_reader<Io>(self, reader: Io) -> Framed<Io, W, C, F, In, Out> {
45        Framed {
46            read_state: read::State::new(reader, Buffer::with_capacity(64)),
47            write_state: self.write_state,
48            codec: self.codec,
49            framer: self.framer,
50            types: PhantomData,
51        }
52    }
53
54    /// Change the writer of the `Framed` object.
55    pub fn with_writer<Io>(self, writer: Io) -> Framed<R, Io, C, F, In, Out> {
56        Framed {
57            read_state: self.read_state,
58            write_state: write::State::new(writer, Vec::new()),
59            codec: self.codec,
60            framer: self.framer,
61            types: PhantomData,
62        }
63    }
64
65    /// Change the codec of the `Framed` object.
66    ///
67    /// This is useful when you have a duplex I/O type, e.g., a
68    /// `compio::net::TcpStream` or `compio::fs::File`, and you want
69    /// [`Framed`] to implement both [`Sink`](futures_util::Sink) and
70    /// [`Stream`](futures_util::Stream).
71    ///
72    /// Some types like the ones mentioned above are multiplexed by nature, so
73    /// they implement the [`Splittable`] trait by themselves. For other types,
74    /// you may want to wrap them in [`Split`] first, which uses lock or
75    /// `RefCell` under the hood.
76    ///
77    /// [`Split`]: crate::util::split::Split
78    pub fn with_duplex<Io: Splittable>(
79        self,
80        io: Io,
81    ) -> Framed<Io::ReadHalf, Io::WriteHalf, C, F, In, Out> {
82        let (read_half, write_half) = io.split();
83
84        Framed {
85            read_state: read::State::new(read_half, Buffer::with_capacity(64)),
86            write_state: write::State::new(write_half, Vec::new()),
87            codec: self.codec,
88            framer: self.framer,
89            types: PhantomData,
90        }
91    }
92}
93
94impl<C, F> Framed<(), (), C, F, (), ()> {
95    /// Creates a new `Framed` with the given I/O object, codec, framer and a
96    /// different input and output type.
97    pub fn new<In, Out>(codec: C, framer: F) -> Framed<(), (), C, F, In, Out> {
98        Framed {
99            read_state: read::State::empty(),
100            write_state: write::State::empty(),
101            codec,
102            framer,
103            types: PhantomData,
104        }
105    }
106
107    /// Creates a new `Framed` with the given I/O object, codec, and framer with
108    /// the same input and output type.
109    pub fn symmetric<T>(codec: C, framer: F) -> Framed<(), (), C, F, T, T> {
110        Framed {
111            read_state: read::State::empty(),
112            write_state: write::State::empty(),
113            codec,
114            framer,
115            types: PhantomData,
116        }
117    }
118}