├── rust-toolchain ├── .gitignore ├── rustfmt.toml ├── src ├── lib.rs ├── async_codec.rs ├── sync_codec.rs ├── framed.rs └── length_delimited.rs ├── Cargo.toml ├── README.md ├── LICENSE-MIT ├── LICENSE-THIRD-PARTY ├── tests └── framed_read.rs └── LICENSE-APACHE /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | comment_width = 100 2 | edition = "2021" 3 | format_code_in_doc_comments = true 4 | format_strings = true 5 | group_imports = "StdExternalCrate" 6 | imports_granularity = "Crate" 7 | normalize_comments = true 8 | normalize_doc_attributes = true 9 | wrap_comments = true 10 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(stable_features)] 2 | 3 | mod async_codec; 4 | mod framed; 5 | pub mod length_delimited; 6 | mod sync_codec; 7 | 8 | pub use async_codec::{AsyncDecoder, AsyncEncoder}; 9 | #[deprecated] 10 | pub use framed::StreamWithCodec as NextWithCodec; 11 | pub use framed::{Framed, FramedRead, FramedWrite, SinkWithCodec, StreamWithCodec}; 12 | pub use sync_codec::{Decoded, Decoder, Encoder}; 13 | -------------------------------------------------------------------------------- /src/async_codec.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | pub trait AsyncEncoder { 4 | type Error: From; 5 | type EncodeFuture<'a>: std::future::Future> 6 | where 7 | Self: 'a; 8 | 9 | fn encode(&mut self, item: Item, dst: &mut IO) -> Self::EncodeFuture<'_>; 10 | } 11 | 12 | pub trait AsyncDecoder { 13 | type Item; 14 | type Error: From; 15 | type DecodeFuture<'a>: std::future::Future, Self::Error>> 16 | where 17 | Self: 'a; 18 | 19 | fn decode(&mut self, src: &mut IO) -> Self::DecodeFuture<'_>; 20 | } 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["ChiHai "] 3 | categories = ["asynchronous", "network-programming"] 4 | description = "Codec for Monoio." 5 | edition = "2021" 6 | keywords = ["runtime", "iouring", "async"] 7 | license = "MIT/Apache-2.0" 8 | name = "monoio-codec" 9 | readme = "README.md" 10 | repository = "https://github.com/monoio-rs/monoio-codec" 11 | version = "0.3.4" 12 | 13 | [dependencies] 14 | bytes = { version = "1" } 15 | monoio = { version = "0.2.0", default_features = false, features = ["bytes"] } 16 | tokio-util = { version = "0.7", default_features = false, features = ["codec"] } 17 | 18 | [dev-dependencies] 19 | monoio = { version = "0.2.0", features = ["macros"] } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Monoio-codec 2 | 3 | [![Crates.io][crates-badge]][crates-url] 4 | [![MIT/Apache-2 licensed][license-badge]][license-url] 5 | 6 | [crates-badge]: https://img.shields.io/crates/v/monoio-codec.svg 7 | [crates-url]: https://crates.io/crates/monoio-codec 8 | [license-badge]: https://img.shields.io/crates/l/monoio-codec.svg 9 | [license-url]: LICENSE-MIT 10 | 11 | This crate provides 2 utils: 12 | 1. `Framed`, `FramedRead` and `FramedWrite`: Like the same things in tokio-util, but with monoio pure async `AsyncReadRent`, `AsyncWriteRent`, `Sink` and `Stream`. 13 | 2. `AsyncEncoder`, `AsyncDecoder`: Trait for encode and decode in async streaming way. 14 | 15 | If the target codec is designed such that all required data lengths can be read from the header at low cost, using synchronous codec can lead to better performance. If not, you can use our async codec trait. 16 | 17 | Note: These 2 modes can be used at the same time because our `Framed` is also a `BufIo`. It implements `AsyncReadRent` and `AsyncWriteRent`. If users know how much data to read, read directly from it can avoid data copy or buffer growth. 18 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Monoio Contributors 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /LICENSE-THIRD-PARTY: -------------------------------------------------------------------------------- 1 | Third party project code used by this project: tokio-util 2 | 3 | =============================================================================== 4 | Copyright (c) 2022 Tokio Contributors 5 | 6 | Permission is hereby granted, free of charge, to any 7 | person obtaining a copy of this software and associated 8 | documentation files (the "Software"), to deal in the 9 | Software without restriction, including without 10 | limitation the rights to use, copy, modify, merge, 11 | publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software 13 | is furnished to do so, subject to the following 14 | conditions: 15 | 16 | The above copyright notice and this permission notice 17 | shall be included in all copies or substantial portions 18 | of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 21 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 22 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 23 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 24 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 27 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /src/sync_codec.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | use bytes::BytesMut; 4 | use monoio::io::{AsyncReadRent, AsyncWriteRent}; 5 | pub use tokio_util::codec::Encoder; 6 | 7 | use crate::Framed; 8 | 9 | /// Decoder may return Decoded to represent a decoded item, 10 | /// or the insufficient length hint, or just the insufficient. 11 | #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] 12 | pub enum Decoded { 13 | Some(T), 14 | // The length needed is unknown. 15 | // Same as None in tokio_codec::Decoder 16 | Insufficient, 17 | // The total length needed. 18 | InsufficientAtLeast(usize), 19 | } 20 | 21 | impl Decoded { 22 | #[inline] 23 | pub fn unwrap(self) -> T { 24 | match self { 25 | Decoded::Some(inner) => inner, 26 | Decoded::Insufficient => panic!("unwrap Decoded::Insufficient"), 27 | Decoded::InsufficientAtLeast(_) => panic!("unwrap Decoded::InsufficientAtLeast"), 28 | } 29 | } 30 | } 31 | 32 | pub trait Decoder { 33 | /// The type of decoded frames. 34 | type Item; 35 | 36 | /// The type of unrecoverable frame decoding errors. 37 | /// 38 | /// If an individual message is ill-formed but can be ignored without 39 | /// interfering with the processing of future messages, it may be more 40 | /// useful to report the failure as an `Item`. 41 | /// 42 | /// `From` is required in the interest of making `Error` suitable 43 | /// for returning directly from a [`FramedRead`], and to enable the default 44 | /// implementation of `decode_eof` to yield an `io::Error` when the decoder 45 | /// fails to consume all available data. 46 | /// 47 | /// Note that implementors of this trait can simply indicate `type Error = 48 | /// io::Error` to use I/O errors as this type. 49 | /// 50 | /// [`FramedRead`]: crate::codec::FramedRead 51 | type Error: From; 52 | 53 | /// Attempts to decode a frame from the provided buffer of bytes. 54 | /// 55 | /// This method is called by [`FramedRead`] whenever bytes are ready to be 56 | /// parsed. The provided buffer of bytes is what's been read so far, and 57 | /// this instance of `Decode` can determine whether an entire frame is in 58 | /// the buffer and is ready to be returned. 59 | /// 60 | /// If an entire frame is available, then this instance will remove those 61 | /// bytes from the buffer provided and return them as a decoded 62 | /// frame. Note that removing bytes from the provided buffer doesn't always 63 | /// necessarily copy the bytes, so this should be an efficient operation in 64 | /// most circumstances. 65 | /// 66 | /// If the bytes look valid, but a frame isn't fully available yet, then 67 | /// `Ok(InsufficientUnknown)` is returned. This indicates to the [`Framed`] instance that 68 | /// it needs to read some more bytes before calling this method again. 69 | /// 70 | /// Note that the bytes provided may be empty. If a previous call to 71 | /// `decode` consumed all the bytes in the buffer then `decode` will be 72 | /// called again until it returns `Ok(InsufficientUnknown)`, indicating that more bytes need to 73 | /// be read. 74 | /// 75 | /// Finally, if the bytes in the buffer are malformed then an error is 76 | /// returned indicating why. This informs [`Framed`] that the stream is now 77 | /// corrupt and should be terminated. 78 | /// 79 | /// [`Framed`]: crate::codec::Framed 80 | /// [`FramedRead`]: crate::codec::FramedRead 81 | fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error>; 82 | 83 | /// A default method available to be called when there are no more bytes 84 | /// available to be read from the underlying I/O. 85 | /// 86 | /// This method defaults to calling `decode` and returns an error if 87 | /// `Ok(None)` is returned while there is unconsumed data in `buf`. 88 | /// Typically this doesn't need to be implemented unless the framing 89 | /// protocol differs near the end of the stream, or if you need to construct 90 | /// frames _across_ eof boundaries on sources that can be resumed. 91 | /// 92 | /// Note that the `buf` argument may be empty. If a previous call to 93 | /// `decode_eof` consumed all the bytes in the buffer, `decode_eof` will be 94 | /// called again until it returns `None`, indicating that there are no more 95 | /// frames to yield. This behavior enables returning finalization frames 96 | /// that may not be based on inbound data. 97 | /// 98 | /// Once `None` has been returned, `decode_eof` won't be called again until 99 | /// an attempt to resume the stream has been made, where the underlying stream 100 | /// actually returned more data. 101 | fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { 102 | match self.decode(buf)? { 103 | Decoded::Some(frame) => Ok(Decoded::Some(frame)), 104 | d => { 105 | if buf.is_empty() { 106 | Ok(d) 107 | } else { 108 | Err(io::Error::new(io::ErrorKind::Other, "bytes remaining on stream").into()) 109 | } 110 | } 111 | } 112 | } 113 | 114 | /// Provides a [`Stream`] and [`Sink`] interface for reading and writing to this 115 | /// `Io` object, using `Decode` and `Encode` to read and write the raw data. 116 | /// 117 | /// Raw I/O objects work with byte sequences, but higher-level code usually 118 | /// wants to batch these into meaningful chunks, called "frames". This 119 | /// method layers framing on top of an I/O object, by using the `Codec` 120 | /// traits to handle encoding and decoding of messages frames. Note that 121 | /// the incoming and outgoing frame types may be distinct. 122 | /// 123 | /// This function returns a *single* object that is both `Stream` and 124 | /// `Sink`; grouping this into a single object is often useful for layering 125 | /// things like gzip or TLS, which require both read and write access to the 126 | /// underlying object. 127 | /// 128 | /// If you want to work more directly with the streams and sink, consider 129 | /// calling `split` on the [`Framed`] returned by this method, which will 130 | /// break them into separate objects, allowing them to interact more easily. 131 | /// 132 | /// [`Stream`]: futures_core::Stream 133 | /// [`Sink`]: futures_sink::Sink 134 | /// [`Framed`]: crate::Framed 135 | fn framed(self, io: T) -> Framed 136 | where 137 | Self: Sized, 138 | { 139 | Framed::new(io, self) 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /tests/framed_read.rs: -------------------------------------------------------------------------------- 1 | // Part of the helper functions and tests are borrowed from tokio-util. 2 | #![allow(stable_features)] 3 | 4 | use std::{collections::VecDeque, io}; 5 | 6 | use bytes::{Buf, BytesMut}; 7 | use monoio::{ 8 | buf::RawBuf, 9 | io::{stream::Stream, AsyncReadRent}, 10 | BufResult, 11 | }; 12 | use monoio_codec::{Decoded, Decoder, FramedRead}; 13 | 14 | macro_rules! mock { 15 | ($($x:expr,)*) => {{ 16 | let mut v = VecDeque::new(); 17 | v.extend(vec![$($x),*]); 18 | Mock { calls: v } 19 | }}; 20 | } 21 | 22 | macro_rules! assert_read_next { 23 | ($e:expr, $n:expr) => {{ 24 | assert_eq!($e.next().await.unwrap().unwrap(), $n); 25 | }}; 26 | } 27 | 28 | macro_rules! assert_read_next_none { 29 | ($e:expr) => {{ 30 | assert!($e.next().await.is_none()); 31 | }}; 32 | } 33 | 34 | macro_rules! assert_read_next_err { 35 | ($e:expr) => {{ 36 | assert!($e.next().await.unwrap().is_err()); 37 | }}; 38 | } 39 | 40 | struct U32Decoder; 41 | 42 | impl Decoder for U32Decoder { 43 | type Item = u32; 44 | type Error = io::Error; 45 | 46 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 47 | if buf.len() < 4 { 48 | return Ok(Decoded::InsufficientAtLeast(4)); 49 | } 50 | 51 | let n = buf.split_to(4).get_u32(); 52 | Ok(Decoded::Some(n)) 53 | } 54 | } 55 | 56 | struct U64Decoder; 57 | 58 | impl Decoder for U64Decoder { 59 | type Item = u64; 60 | type Error = io::Error; 61 | 62 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 63 | if buf.len() < 8 { 64 | return Ok(Decoded::InsufficientAtLeast(8)); 65 | } 66 | 67 | let n = buf.split_to(8).get_u64(); 68 | Ok(Decoded::Some(n)) 69 | } 70 | } 71 | 72 | #[monoio::test_all] 73 | async fn read_multi_frame_in_packet() { 74 | let mock = mock! { 75 | Ok(b"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()), 76 | }; 77 | 78 | let mut framed = FramedRead::new(mock, U32Decoder); 79 | assert_read_next!(framed, 0); 80 | assert_read_next!(framed, 1); 81 | assert_read_next!(framed, 2); 82 | assert!(framed.next().await.is_none()); 83 | } 84 | 85 | #[monoio::test_all] 86 | async fn read_multi_frame_across_packets() { 87 | let mock = mock! { 88 | Ok(b"\x00\x00\x00\x00".to_vec()), 89 | Ok(b"\x00\x00\x00\x01".to_vec()), 90 | Ok(b"\x00\x00\x00\x02".to_vec()), 91 | }; 92 | 93 | let mut framed = FramedRead::new(mock, U32Decoder); 94 | assert_read_next!(framed, 0); 95 | assert_read_next!(framed, 1); 96 | assert_read_next!(framed, 2); 97 | assert_read_next_none!(framed); 98 | } 99 | 100 | #[monoio::test_all] 101 | async fn read_multi_frame_in_packet_after_codec_changed() { 102 | let mock = mock! { 103 | Ok(b"\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x08".to_vec()), 104 | }; 105 | let mut framed = FramedRead::new(mock, U32Decoder); 106 | assert_read_next!(framed, 0x04); 107 | 108 | let mut framed = framed.map_decoder(|_| U64Decoder); 109 | assert_read_next!(framed, 0x08); 110 | assert_read_next_none!(framed); 111 | } 112 | 113 | #[monoio::test_all] 114 | async fn read_err() { 115 | let mock = mock! { 116 | Err(io::Error::new(io::ErrorKind::Other, "")), 117 | }; 118 | 119 | let mut framed = FramedRead::new(mock, U32Decoder); 120 | assert_eq!( 121 | framed.next().await.unwrap().unwrap_err().kind(), 122 | io::ErrorKind::Other 123 | ); 124 | } 125 | 126 | #[monoio::test_all] 127 | async fn read_partial_then_err() { 128 | let mock = mock! { 129 | Ok(b"\x00\x00".to_vec()), 130 | Err(io::Error::new(io::ErrorKind::Other, "")), 131 | }; 132 | 133 | let mut framed = FramedRead::new(mock, U32Decoder); 134 | assert_eq!( 135 | framed.next().await.unwrap().unwrap_err().kind(), 136 | io::ErrorKind::Other 137 | ); 138 | } 139 | 140 | #[monoio::test_all] 141 | async fn huge_size() { 142 | let data = &[0; 32 * 1024][..]; 143 | let mut framed = FramedRead::new(data, BigDecoder); 144 | 145 | assert_read_next!(framed, 0); 146 | assert_read_next_none!(framed); 147 | 148 | struct BigDecoder; 149 | impl Decoder for BigDecoder { 150 | type Item = u32; 151 | type Error = io::Error; 152 | 153 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 154 | const CNT: usize = 32 * 1024; 155 | if buf.len() < CNT { 156 | return Ok(Decoded::InsufficientAtLeast(CNT)); 157 | } 158 | buf.advance(CNT); 159 | Ok(Decoded::Some(0)) 160 | } 161 | } 162 | } 163 | 164 | #[monoio::test_all] 165 | async fn data_remaining_is_error() { 166 | let slice = &[0; 5][..]; 167 | let mut framed = FramedRead::new(slice, U32Decoder); 168 | 169 | assert_read_next!(framed, 0); 170 | assert_read_next_err!(framed); 171 | } 172 | 173 | #[monoio::test_all] 174 | async fn multi_frames_on_eof() { 175 | struct MyDecoder(Vec); 176 | 177 | impl Decoder for MyDecoder { 178 | type Item = u32; 179 | type Error = io::Error; 180 | 181 | fn decode(&mut self, _buf: &mut BytesMut) -> io::Result> { 182 | unreachable!(); 183 | } 184 | 185 | fn decode_eof(&mut self, _buf: &mut BytesMut) -> io::Result> { 186 | if self.0.is_empty() { 187 | return Ok(Decoded::Insufficient); 188 | } 189 | 190 | Ok(Decoded::Some(self.0.remove(0))) 191 | } 192 | } 193 | 194 | let mut framed = FramedRead::new(mock!(), MyDecoder(vec![0, 1, 2, 3])); 195 | assert_read_next!(framed, 0); 196 | assert_read_next!(framed, 1); 197 | assert_read_next!(framed, 2); 198 | assert_read_next!(framed, 3); 199 | assert_read_next_none!(framed); 200 | } 201 | 202 | #[monoio::test_all] 203 | async fn read_eof_then_resume() { 204 | let mock = mock! { 205 | Ok(b"\x00\x00\x00\x01".to_vec()), 206 | Ok(b"".to_vec()), 207 | Ok(b"\x00\x00\x00\x02".to_vec()), 208 | Ok(b"".to_vec()), 209 | Ok(b"\x00\x00\x00\x03".to_vec()), 210 | }; 211 | let mut framed = FramedRead::new(mock, U32Decoder); 212 | assert_read_next!(framed, 1); 213 | assert_read_next_none!(framed); 214 | assert_read_next!(framed, 2); 215 | assert_read_next_none!(framed); 216 | assert_read_next!(framed, 3); 217 | assert_read_next_none!(framed); 218 | assert_read_next_none!(framed); 219 | } 220 | 221 | struct Mock { 222 | calls: VecDeque>>, 223 | } 224 | 225 | use monoio::buf::{IoBufMut, IoVecBufMut}; 226 | 227 | impl AsyncReadRent for Mock { 228 | async fn read(&mut self, mut buf: T) -> BufResult { 229 | match self.calls.pop_front() { 230 | Some(Ok(data)) => { 231 | let n = data.len(); 232 | debug_assert!(buf.bytes_total() >= n); 233 | unsafe { 234 | buf.write_ptr().copy_from_nonoverlapping(data.as_ptr(), n); 235 | buf.set_init(n) 236 | } 237 | (Ok(n), buf) 238 | } 239 | Some(Err(e)) => (Err(e), buf), 240 | None => (Ok(0), buf), 241 | } 242 | } 243 | 244 | async fn readv(&mut self, mut buf: T) -> BufResult { 245 | let n = match unsafe { RawBuf::new_from_iovec_mut(&mut buf) } { 246 | Some(raw_buf) => self.read(raw_buf).await.0, 247 | None => Ok(0), 248 | }; 249 | if let Ok(n) = n { 250 | unsafe { buf.set_init(n) }; 251 | } 252 | (n, buf) 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Monoio Contributors 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /src/framed.rs: -------------------------------------------------------------------------------- 1 | // Part of the helper functions and tests are borrowed from tokio-util. 2 | 3 | use std::{ 4 | borrow::{Borrow, BorrowMut}, 5 | fmt, 6 | future::Future, 7 | }; 8 | 9 | use bytes::{Buf, BufMut, BytesMut}; 10 | use monoio::{ 11 | buf::{IoBuf, IoBufMut, IoVecBuf, IoVecBufMut, IoVecWrapperMut, SliceMut}, 12 | io::{sink::Sink, stream::Stream, AsyncReadRent, AsyncWriteRent, AsyncWriteRentExt}, 13 | BufResult, 14 | }; 15 | 16 | use crate::{Decoded, Decoder, Encoder}; 17 | 18 | const INITIAL_CAPACITY: usize = 8 * 1024; 19 | const BACKPRESSURE_BOUNDARY: usize = INITIAL_CAPACITY; 20 | const RESERVE: usize = 4096; 21 | 22 | pub struct FramedInner { 23 | io: IO, 24 | codec: Codec, 25 | state: S, 26 | } 27 | 28 | #[derive(Debug)] 29 | pub struct ReadState { 30 | state: State, 31 | buffer: BytesMut, 32 | } 33 | 34 | impl ReadState { 35 | #[inline] 36 | fn with_capacity(capacity: usize) -> Self { 37 | Self { 38 | state: State::Framing(None), 39 | buffer: BytesMut::with_capacity(capacity), 40 | } 41 | } 42 | } 43 | 44 | impl Default for ReadState { 45 | #[inline] 46 | fn default() -> Self { 47 | Self::with_capacity(INITIAL_CAPACITY) 48 | } 49 | } 50 | 51 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 52 | enum State { 53 | Framing(Option), 54 | Pausing, 55 | Paused, 56 | Errored, 57 | } 58 | 59 | #[derive(Debug)] 60 | pub struct WriteState { 61 | buffer: BytesMut, 62 | } 63 | 64 | impl Default for WriteState { 65 | #[inline] 66 | fn default() -> Self { 67 | Self { 68 | buffer: BytesMut::with_capacity(INITIAL_CAPACITY), 69 | } 70 | } 71 | } 72 | 73 | #[derive(Debug, Default)] 74 | pub struct RWState { 75 | read: ReadState, 76 | write: WriteState, 77 | } 78 | 79 | impl Borrow for RWState { 80 | #[inline] 81 | fn borrow(&self) -> &ReadState { 82 | &self.read 83 | } 84 | } 85 | impl BorrowMut for RWState { 86 | #[inline] 87 | fn borrow_mut(&mut self) -> &mut ReadState { 88 | &mut self.read 89 | } 90 | } 91 | impl Borrow for RWState { 92 | #[inline] 93 | fn borrow(&self) -> &WriteState { 94 | &self.write 95 | } 96 | } 97 | impl BorrowMut for RWState { 98 | #[inline] 99 | fn borrow_mut(&mut self) -> &mut WriteState { 100 | &mut self.write 101 | } 102 | } 103 | 104 | impl FramedInner { 105 | #[inline] 106 | const fn new(io: IO, codec: Codec, state: S) -> Self { 107 | Self { io, codec, state } 108 | } 109 | 110 | async fn peek_data<'a, 'b>(io: &'b mut IO, state: &'a mut S) -> std::io::Result<&'a mut [u8]> 111 | where 112 | IO: AsyncReadRent, 113 | S: BorrowMut, 114 | { 115 | let read_state: &mut ReadState = state.borrow_mut(); 116 | let state = &mut read_state.state; 117 | let buffer = &mut read_state.buffer; 118 | 119 | if !buffer.is_empty() { 120 | return Ok(buffer.as_mut()); 121 | } 122 | buffer.reserve(RESERVE); 123 | 124 | macro_rules! ok { 125 | ($result: expr, $state: expr) => { 126 | match $result { 127 | Ok(x) => x, 128 | Err(e) => { 129 | *$state = State::Errored; 130 | return Err(e); 131 | } 132 | } 133 | }; 134 | } 135 | 136 | // Read data 137 | let end = buffer.capacity(); 138 | let owned_buf = std::mem::take(buffer); 139 | let owned_slice = unsafe { SliceMut::new_unchecked(owned_buf, 0, end) }; 140 | let (result, owned_slice) = io.read(owned_slice).await; 141 | *buffer = owned_slice.into_inner(); 142 | let n = ok!(result, state); 143 | if n == 0 { 144 | *state = State::Paused; 145 | } 146 | Ok(buffer.as_mut()) 147 | } 148 | 149 | // In tokio there are 5 states. But since we use pure async here, 150 | // we do not need to return Pending so we don't need to save the state 151 | // when Pending returned. We only need to save state when return 152 | // `Option`. 153 | // We have 4 states: Framing, Pausing, Paused and Errored. 154 | async fn next_with( 155 | io: &mut IO, 156 | codec: &mut Codec, 157 | state: &mut S, 158 | ) -> Option> 159 | where 160 | IO: AsyncReadRent, 161 | Codec: Decoder, 162 | S: BorrowMut, 163 | { 164 | macro_rules! ok { 165 | ($result: expr, $state: expr) => { 166 | match $result { 167 | Ok(x) => x, 168 | Err(e) => { 169 | *$state = State::Errored; 170 | return Some(Err(e.into())); 171 | } 172 | } 173 | }; 174 | } 175 | 176 | let read_state: &mut ReadState = state.borrow_mut(); 177 | let state = &mut read_state.state; 178 | let buffer = &mut read_state.buffer; 179 | 180 | loop { 181 | match state { 182 | // On framing, we will decode first. If the decoder needs more data, 183 | // we will do read and await it. 184 | // If we get an error or eof, we will transfer state. 185 | State::Framing(hint) => loop { 186 | if !matches!(hint, Some(size) if buffer.len() < *size) && !buffer.is_empty() { 187 | // If we get a Some hint and the buffer length is less than it, we do not 188 | // decode. If the buffer is empty, we we do not decode. 189 | *hint = match ok!(codec.decode(buffer), state) { 190 | Decoded::Some(item) => { 191 | // When we decoded something, we should clear the hint. 192 | *hint = None; 193 | return Some(Ok(item)); 194 | } 195 | Decoded::Insufficient => None, 196 | Decoded::InsufficientAtLeast(size) => Some(size), 197 | }; 198 | } 199 | 200 | let reserve = match *hint { 201 | Some(size) if size > buffer.len() => RESERVE.max(size - buffer.len()), 202 | _ => RESERVE, 203 | }; 204 | buffer.reserve(reserve); 205 | let (begin, end) = { 206 | let buffer_ptr = buffer.write_ptr(); 207 | let slice_to_write = buffer.chunk_mut(); 208 | let begin = 209 | unsafe { slice_to_write.as_mut_ptr().offset_from(buffer_ptr) } as usize; 210 | let end = begin + slice_to_write.len(); 211 | (begin, end) 212 | }; 213 | let owned_buf = std::mem::take(buffer); 214 | let owned_slice = unsafe { SliceMut::new_unchecked(owned_buf, begin, end) }; 215 | let (result, owned_slice) = io.read(owned_slice).await; 216 | *buffer = owned_slice.into_inner(); 217 | let n = ok!(result, state); 218 | if n == 0 { 219 | *state = State::Pausing; 220 | break; 221 | } 222 | }, 223 | // On Pausing, we will loop decode_eof until None or Error. 224 | State::Pausing => { 225 | return match ok!(codec.decode_eof(buffer), state) { 226 | Decoded::Some(item) => Some(Ok(item)), 227 | _ => { 228 | // Buffer has no data, we can transfer to Paused. 229 | *state = State::Paused; 230 | None 231 | } 232 | }; 233 | } 234 | // On Paused, we need to read directly. 235 | State::Paused => { 236 | buffer.reserve(RESERVE); 237 | let (begin, end) = { 238 | let buffer_ptr = buffer.write_ptr(); 239 | let slice_to_write = buffer.chunk_mut(); 240 | let begin = 241 | unsafe { slice_to_write.as_mut_ptr().offset_from(buffer_ptr) } as usize; 242 | let end = begin + slice_to_write.len(); 243 | (begin, end) 244 | }; 245 | let owned_buf = std::mem::take(buffer); 246 | let owned_slice = unsafe { SliceMut::new_unchecked(owned_buf, begin, end) }; 247 | let (result, owned_slice) = io.read(owned_slice).await; 248 | *buffer = owned_slice.into_inner(); 249 | let n = ok!(result, state); 250 | if n == 0 { 251 | // still paused 252 | return None; 253 | } 254 | // read something, then we move to framing state 255 | *state = State::Framing(None); 256 | } 257 | // On Errored, we need to return None and trans to Paused. 258 | State::Errored => { 259 | *state = State::Paused; 260 | return None; 261 | } 262 | } 263 | } 264 | } 265 | 266 | async fn flush(io: &mut IO, state: &mut S) -> std::io::Result<()> 267 | where 268 | IO: AsyncWriteRent, 269 | S: BorrowMut, 270 | { 271 | let WriteState { buffer } = state.borrow_mut(); 272 | if buffer.is_empty() { 273 | return Ok(()); 274 | } 275 | // This action does not allocate. 276 | let buf = std::mem::take(buffer); 277 | let (result, buf) = io.write_all(buf).await; 278 | *buffer = buf; 279 | result?; 280 | buffer.clear(); 281 | io.flush().await?; 282 | Ok(()) 283 | } 284 | 285 | #[inline] 286 | async fn send_with( 287 | io: &mut IO, 288 | codec: &mut Codec, 289 | state: &mut S, 290 | item: Item, 291 | ) -> Result<(), Codec::Error> 292 | where 293 | IO: AsyncWriteRent, 294 | Codec: Encoder, 295 | S: BorrowMut, 296 | { 297 | if state.borrow_mut().buffer.len() >= BACKPRESSURE_BOUNDARY { 298 | Self::flush(io, state).await?; 299 | } 300 | codec.encode(item, &mut state.borrow_mut().buffer)?; 301 | Ok(()) 302 | } 303 | } 304 | 305 | impl AsyncReadRent for FramedInner 306 | where 307 | IO: AsyncReadRent, 308 | S: BorrowMut, 309 | { 310 | async fn read(&mut self, mut buf: T) -> BufResult { 311 | let read_state: &mut ReadState = self.state.borrow_mut(); 312 | let state = &mut read_state.state; 313 | let buffer = &mut read_state.buffer; 314 | 315 | if buf.bytes_total() == 0 { 316 | return (Ok(0), buf); 317 | } 318 | 319 | // Copy existing data if there is some. 320 | let to_copy = buf.bytes_total().min(buffer.len()); 321 | if to_copy != 0 { 322 | unsafe { 323 | buf.write_ptr() 324 | .copy_from_nonoverlapping(buffer.as_ptr(), to_copy); 325 | buf.set_init(to_copy); 326 | } 327 | buffer.advance(to_copy); 328 | return (Ok(to_copy), buf); 329 | } 330 | 331 | // Read to buf directly if buf size is bigger than some threshold. 332 | if buf.bytes_total() > INITIAL_CAPACITY { 333 | let (res, buf) = self.io.read(buf).await; 334 | return match res { 335 | Ok(0) => { 336 | *state = State::Pausing; 337 | (Ok(0), buf) 338 | } 339 | Ok(n) => (Ok(n), buf), 340 | Err(e) => { 341 | *state = State::Errored; 342 | (Err(e), buf) 343 | } 344 | }; 345 | } 346 | // Read to inner buffer and copy to buf. 347 | buffer.reserve(INITIAL_CAPACITY); 348 | let owned_buffer = std::mem::take(buffer); 349 | let (res, owned_buffer) = self.io.read(owned_buffer).await; 350 | *buffer = owned_buffer; 351 | match res { 352 | Ok(0) => { 353 | *state = State::Pausing; 354 | return (Ok(0), buf); 355 | } 356 | Err(e) => { 357 | *state = State::Errored; 358 | return (Err(e), buf); 359 | } 360 | _ => (), 361 | } 362 | let to_copy = buf.bytes_total().min(buffer.len()); 363 | unsafe { 364 | buf.write_ptr() 365 | .copy_from_nonoverlapping(buffer.as_ptr(), to_copy); 366 | buf.set_init(to_copy); 367 | } 368 | buffer.advance(to_copy); 369 | (Ok(to_copy), buf) 370 | } 371 | 372 | async fn readv(&mut self, mut buf: T) -> BufResult { 373 | let slice = match IoVecWrapperMut::new(buf) { 374 | Ok(slice) => slice, 375 | Err(buf) => return (Ok(0), buf), 376 | }; 377 | 378 | let (result, slice) = self.read(slice).await; 379 | buf = slice.into_inner(); 380 | if let Ok(n) = result { 381 | unsafe { buf.set_init(n) }; 382 | } 383 | (result, buf) 384 | } 385 | } 386 | 387 | impl Stream for FramedInner 388 | where 389 | IO: AsyncReadRent, 390 | Codec: Decoder, 391 | S: BorrowMut, 392 | { 393 | type Item = Result; 394 | 395 | #[inline] 396 | async fn next(&mut self) -> Option { 397 | Self::next_with(&mut self.io, &mut self.codec, &mut self.state).await 398 | } 399 | } 400 | 401 | impl AsyncWriteRent for FramedInner 402 | where 403 | IO: AsyncWriteRent, 404 | S: BorrowMut, 405 | { 406 | async fn write(&mut self, buf: T) -> BufResult { 407 | let WriteState { buffer } = self.state.borrow_mut(); 408 | if buffer.len() >= BACKPRESSURE_BOUNDARY || buf.bytes_init() >= INITIAL_CAPACITY { 409 | // flush buffer 410 | if let Err(e) = AsyncWriteRent::flush(self).await { 411 | return (Err(e), buf); 412 | } 413 | // write directly 414 | return self.io.write_all(buf).await; 415 | } 416 | // copy to buffer 417 | let cap = buffer.capacity() - buffer.len(); 418 | let size = buf.bytes_init().min(cap); 419 | let slice = unsafe { std::slice::from_raw_parts(buf.read_ptr(), size) }; 420 | buffer.extend_from_slice(slice); 421 | (Ok(size), buf) 422 | } 423 | 424 | #[inline] 425 | async fn writev(&mut self, buf: T) -> BufResult { 426 | let slice = match monoio::buf::IoVecWrapper::new(buf) { 427 | Ok(slice) => slice, 428 | Err(buf) => return (Ok(0), buf), 429 | }; 430 | 431 | let (result, slice) = self.write(slice).await; 432 | (result, slice.into_inner()) 433 | } 434 | 435 | #[inline] 436 | async fn flush(&mut self) -> std::io::Result<()> { 437 | FramedInner::<_, Codec, _>::flush(&mut self.io, &mut self.state).await 438 | } 439 | 440 | #[inline] 441 | async fn shutdown(&mut self) -> std::io::Result<()> { 442 | AsyncWriteRent::flush(self).await?; 443 | self.io.shutdown().await?; 444 | Ok(()) 445 | } 446 | } 447 | 448 | impl Sink for FramedInner 449 | where 450 | IO: AsyncWriteRent, 451 | Codec: Encoder, 452 | S: BorrowMut, 453 | { 454 | type Error = Codec::Error; 455 | 456 | #[inline] 457 | async fn send(&mut self, item: Item) -> Result<(), Self::Error> { 458 | if self.state.borrow_mut().buffer.len() >= BACKPRESSURE_BOUNDARY { 459 | FramedInner::<_, Codec, _>::flush(&mut self.io, &mut self.state).await?; 460 | } 461 | self.codec 462 | .encode(item, &mut self.state.borrow_mut().buffer)?; 463 | Ok(()) 464 | } 465 | 466 | #[inline] 467 | async fn flush(&mut self) -> Result<(), Self::Error> { 468 | AsyncWriteRent::flush(self).await?; 469 | Ok(()) 470 | } 471 | 472 | #[inline] 473 | async fn close(&mut self) -> Result<(), Self::Error> { 474 | AsyncWriteRent::shutdown(self).await?; 475 | Ok(()) 476 | } 477 | } 478 | 479 | pub struct Framed { 480 | inner: FramedInner, 481 | } 482 | 483 | pub struct FramedRead { 484 | inner: FramedInner, 485 | } 486 | 487 | pub struct FramedWrite { 488 | inner: FramedInner, 489 | } 490 | 491 | impl Framed { 492 | #[inline] 493 | pub fn new(io: IO, codec: Codec) -> Self { 494 | Self { 495 | inner: FramedInner::new(io, codec, RWState::default()), 496 | } 497 | } 498 | 499 | #[inline] 500 | pub fn with_capacity(io: IO, codec: Codec, capacity: usize) -> Self { 501 | Self { 502 | inner: FramedInner::new( 503 | io, 504 | codec, 505 | RWState { 506 | read: ReadState::with_capacity(capacity), 507 | write: Default::default(), 508 | }, 509 | ), 510 | } 511 | } 512 | 513 | /// Returns a reference to the underlying I/O stream wrapped by 514 | /// `Framed`. 515 | /// 516 | /// Note that care should be taken to not tamper with the underlying stream 517 | /// of data coming in as it may corrupt the stream of frames otherwise 518 | /// being worked with. 519 | #[inline] 520 | pub fn get_ref(&self) -> &IO { 521 | &self.inner.io 522 | } 523 | 524 | /// Returns a mutable reference to the underlying I/O stream wrapped by 525 | /// `Framed`. 526 | /// 527 | /// Note that care should be taken to not tamper with the underlying stream 528 | /// of data coming in as it may corrupt the stream of frames otherwise 529 | /// being worked with. 530 | #[inline] 531 | pub fn get_mut(&mut self) -> &mut IO { 532 | &mut self.inner.io 533 | } 534 | 535 | /// Returns a reference to the underlying codec wrapped by 536 | /// `Framed`. 537 | /// 538 | /// Note that care should be taken to not tamper with the underlying codec 539 | /// as it may corrupt the stream of frames otherwise being worked with. 540 | #[inline] 541 | pub fn codec(&self) -> &Codec { 542 | &self.inner.codec 543 | } 544 | 545 | /// Returns a mutable reference to the underlying codec wrapped by 546 | /// `Framed`. 547 | /// 548 | /// Note that care should be taken to not tamper with the underlying codec 549 | /// as it may corrupt the stream of frames otherwise being worked with. 550 | #[inline] 551 | pub fn codec_mut(&mut self) -> &mut Codec { 552 | &mut self.inner.codec 553 | } 554 | 555 | /// Maps the codec `U` to `C`, preserving the read and write buffers 556 | /// wrapped by `Framed`. 557 | /// 558 | /// Note that care should be taken to not tamper with the underlying codec 559 | /// as it may corrupt the stream of frames otherwise being worked with. 560 | #[inline] 561 | pub fn map_codec(self, map: F) -> Framed 562 | where 563 | F: FnOnce(Codec) -> CodecNew, 564 | { 565 | let FramedInner { io, codec, state } = self.inner; 566 | Framed { 567 | inner: FramedInner { 568 | io, 569 | codec: map(codec), 570 | state, 571 | }, 572 | } 573 | } 574 | 575 | /// Returns a reference to the read buffer. 576 | #[inline] 577 | pub fn read_buffer(&self) -> &BytesMut { 578 | &self.inner.state.read.buffer 579 | } 580 | 581 | /// Returns a mutable reference to the read buffer. 582 | #[inline] 583 | pub fn read_buffer_mut(&mut self) -> &mut BytesMut { 584 | &mut self.inner.state.read.buffer 585 | } 586 | 587 | /// Returns io and a mutable reference to the read buffer. 588 | #[inline] 589 | pub fn read_state_mut(&mut self) -> (&mut IO, &mut BytesMut) { 590 | (&mut self.inner.io, &mut self.inner.state.read.buffer) 591 | } 592 | 593 | /// Returns a reference to the write buffer. 594 | #[inline] 595 | pub fn write_buffer(&self) -> &BytesMut { 596 | &self.inner.state.write.buffer 597 | } 598 | 599 | /// Returns a mutable reference to the write buffer. 600 | #[inline] 601 | pub fn write_buffer_mut(&mut self) -> &mut BytesMut { 602 | &mut self.inner.state.write.buffer 603 | } 604 | 605 | /// Consumes the `Framed`, returning its underlying I/O stream. 606 | /// 607 | /// Note that care should be taken to not tamper with the underlying stream 608 | /// of data coming in as it may corrupt the stream of frames otherwise 609 | /// being worked with. 610 | #[inline] 611 | pub fn into_inner(self) -> IO { 612 | self.inner.io 613 | } 614 | 615 | /// Equivalent to Stream::next but with custom codec. 616 | #[inline] 617 | pub async fn next_with( 618 | &mut self, 619 | codec: &mut C, 620 | ) -> Option> 621 | where 622 | IO: AsyncReadRent, 623 | { 624 | FramedInner::next_with(&mut self.inner.io, codec, &mut self.inner.state).await 625 | } 626 | 627 | /// Await some new data. 628 | /// Useful to do read timeout. 629 | pub fn peek_data(&mut self) -> impl Future> 630 | where 631 | IO: AsyncReadRent, 632 | { 633 | FramedInner::<_, Codec, _>::peek_data(&mut self.inner.io, &mut self.inner.state) 634 | } 635 | 636 | /// Equivalent to Sink::send but with custom codec. 637 | #[inline] 638 | pub async fn send_with, Item>( 639 | &mut self, 640 | codec: &mut C, 641 | item: Item, 642 | ) -> Result<(), C::Error> 643 | where 644 | IO: AsyncWriteRent, 645 | C: Encoder, 646 | { 647 | FramedInner::send_with(&mut self.inner.io, codec, &mut self.inner.state, item).await 648 | } 649 | } 650 | 651 | impl fmt::Debug for Framed 652 | where 653 | T: fmt::Debug, 654 | U: fmt::Debug, 655 | { 656 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 657 | f.debug_struct("Framed") 658 | .field("io", self.get_ref()) 659 | .field("codec", self.codec()) 660 | .finish() 661 | } 662 | } 663 | 664 | impl FramedRead { 665 | pub fn new(io: IO, decoder: Codec) -> Self { 666 | Self { 667 | inner: FramedInner::new(io, decoder, ReadState::default()), 668 | } 669 | } 670 | 671 | pub fn with_capacity(io: IO, codec: Codec, capacity: usize) -> Self { 672 | Self { 673 | inner: FramedInner::new(io, codec, ReadState::with_capacity(capacity)), 674 | } 675 | } 676 | 677 | /// Returns a reference to the underlying I/O stream wrapped by 678 | /// `FramedRead`. 679 | /// 680 | /// Note that care should be taken to not tamper with the underlying stream 681 | /// of data coming in as it may corrupt the stream of frames otherwise 682 | /// being worked with. 683 | pub fn get_ref(&self) -> &IO { 684 | &self.inner.io 685 | } 686 | 687 | /// Returns a mutable reference to the underlying I/O stream wrapped by 688 | /// `FramedRead`. 689 | /// 690 | /// Note that care should be taken to not tamper with the underlying stream 691 | /// of data coming in as it may corrupt the stream of frames otherwise 692 | /// being worked with. 693 | pub fn get_mut(&mut self) -> &mut IO { 694 | &mut self.inner.io 695 | } 696 | 697 | /// Consumes the `FramedRead`, returning its underlying I/O stream. 698 | /// 699 | /// Note that care should be taken to not tamper with the underlying stream 700 | /// of data coming in as it may corrupt the stream of frames otherwise 701 | /// being worked with. 702 | pub fn into_inner(self) -> IO { 703 | self.inner.io 704 | } 705 | 706 | /// Returns a reference to the underlying decoder. 707 | pub fn decoder(&self) -> &Codec { 708 | &self.inner.codec 709 | } 710 | 711 | /// Returns a mutable reference to the underlying decoder. 712 | pub fn decoder_mut(&mut self) -> &mut Codec { 713 | &mut self.inner.codec 714 | } 715 | 716 | /// Maps the decoder `D` to `C`, preserving the read buffer 717 | /// wrapped by `Framed`. 718 | pub fn map_decoder(self, map: F) -> FramedRead 719 | where 720 | F: FnOnce(Codec) -> CodecNew, 721 | { 722 | let FramedInner { io, codec, state } = self.inner; 723 | FramedRead { 724 | inner: FramedInner { 725 | io, 726 | codec: map(codec), 727 | state, 728 | }, 729 | } 730 | } 731 | 732 | /// Returns a reference to the read buffer. 733 | pub fn read_buffer(&self) -> &BytesMut { 734 | &self.inner.state.buffer 735 | } 736 | 737 | /// Returns a mutable reference to the read buffer. 738 | pub fn read_buffer_mut(&mut self) -> &mut BytesMut { 739 | &mut self.inner.state.buffer 740 | } 741 | 742 | /// Returns io and a mutable reference to the read buffer. 743 | pub fn read_state_mut(&mut self) -> (&mut IO, &mut BytesMut) { 744 | (&mut self.inner.io, &mut self.inner.state.buffer) 745 | } 746 | 747 | /// Equivalent to Stream::next but with custom codec. 748 | pub async fn next_with( 749 | &mut self, 750 | codec: &mut C, 751 | ) -> Option> 752 | where 753 | IO: AsyncReadRent, 754 | { 755 | FramedInner::next_with(&mut self.inner.io, codec, &mut self.inner.state).await 756 | } 757 | 758 | /// Await some new data. 759 | /// Useful to do read timeout. 760 | pub fn peek_data(&mut self) -> impl Future> 761 | where 762 | IO: AsyncReadRent, 763 | { 764 | FramedInner::<_, Codec, _>::peek_data(&mut self.inner.io, &mut self.inner.state) 765 | } 766 | } 767 | 768 | impl fmt::Debug for FramedRead 769 | where 770 | T: fmt::Debug, 771 | D: fmt::Debug, 772 | { 773 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 774 | f.debug_struct("FramedRead") 775 | .field("inner", &self.get_ref()) 776 | .field("decoder", &self.decoder()) 777 | .field("state", &self.inner.state.state) 778 | .field("buffer", &self.read_buffer()) 779 | .finish() 780 | } 781 | } 782 | 783 | impl FramedWrite { 784 | pub fn new(io: IO, encoder: Codec) -> Self { 785 | Self { 786 | inner: FramedInner::new(io, encoder, WriteState::default()), 787 | } 788 | } 789 | 790 | /// Returns a reference to the underlying I/O stream wrapped by 791 | /// `FramedWrite`. 792 | /// 793 | /// Note that care should be taken to not tamper with the underlying stream 794 | /// of data coming in as it may corrupt the stream of frames otherwise 795 | /// being worked with. 796 | pub fn get_ref(&self) -> &IO { 797 | &self.inner.io 798 | } 799 | 800 | /// Returns a mutable reference to the underlying I/O stream wrapped by 801 | /// `FramedWrite`. 802 | /// 803 | /// Note that care should be taken to not tamper with the underlying stream 804 | /// of data coming in as it may corrupt the stream of frames otherwise 805 | /// being worked with. 806 | pub fn get_mut(&mut self) -> &mut IO { 807 | &mut self.inner.io 808 | } 809 | 810 | /// Consumes the `FramedWrite`, returning its underlying I/O stream. 811 | /// 812 | /// Note that care should be taken to not tamper with the underlying stream 813 | /// of data coming in as it may corrupt the stream of frames otherwise 814 | /// being worked with. 815 | pub fn into_inner(self) -> IO { 816 | self.inner.io 817 | } 818 | 819 | /// Returns a reference to the underlying encoder. 820 | pub fn encoder(&self) -> &Codec { 821 | &self.inner.codec 822 | } 823 | 824 | /// Returns a mutable reference to the underlying encoder. 825 | pub fn encoder_mut(&mut self) -> &mut Codec { 826 | &mut self.inner.codec 827 | } 828 | 829 | /// Maps the encoder `E` to `C`, preserving the write buffer 830 | /// wrapped by `Framed`. 831 | pub fn map_encoder(self, map: F) -> FramedWrite 832 | where 833 | F: FnOnce(Codec) -> CodecNew, 834 | { 835 | let FramedInner { io, codec, state } = self.inner; 836 | FramedWrite { 837 | inner: FramedInner { 838 | io, 839 | codec: map(codec), 840 | state, 841 | }, 842 | } 843 | } 844 | 845 | /// Returns a reference to the write buffer. 846 | pub fn write_buffer(&self) -> &BytesMut { 847 | &self.inner.state.buffer 848 | } 849 | 850 | /// Returns a mutable reference to the write buffer. 851 | pub fn write_buffer_mut(&mut self) -> &mut BytesMut { 852 | &mut self.inner.state.buffer 853 | } 854 | } 855 | 856 | impl fmt::Debug for FramedWrite 857 | where 858 | T: fmt::Debug, 859 | U: fmt::Debug, 860 | { 861 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 862 | f.debug_struct("FramedWrite") 863 | .field("inner", &self.get_ref()) 864 | .field("encoder", &self.encoder()) 865 | .field("buffer", &self.inner.state.buffer) 866 | .finish() 867 | } 868 | } 869 | 870 | impl Stream for Framed 871 | where 872 | IO: AsyncReadRent, 873 | Codec: Decoder, 874 | { 875 | type Item = as Stream>::Item; 876 | 877 | #[inline] 878 | async fn next(&mut self) -> Option { 879 | self.inner.next().await 880 | } 881 | } 882 | 883 | impl Stream for FramedRead 884 | where 885 | IO: AsyncReadRent, 886 | Codec: Decoder, 887 | { 888 | type Item = as Stream>::Item; 889 | 890 | #[inline] 891 | async fn next(&mut self) -> Option { 892 | self.inner.next().await 893 | } 894 | } 895 | 896 | impl Sink for Framed 897 | where 898 | IO: AsyncWriteRent, 899 | Codec: Encoder, 900 | { 901 | type Error = as Sink>::Error; 902 | 903 | #[inline] 904 | async fn send(&mut self, item: Item) -> Result<(), Self::Error> { 905 | self.inner.send(item).await 906 | } 907 | 908 | #[inline] 909 | async fn flush(&mut self) -> Result<(), Self::Error> { 910 | Sink::flush(&mut self.inner).await 911 | } 912 | 913 | #[inline] 914 | async fn close(&mut self) -> Result<(), Self::Error> { 915 | self.inner.close().await 916 | } 917 | } 918 | 919 | impl Sink for FramedWrite 920 | where 921 | IO: AsyncWriteRent, 922 | Codec: Encoder, 923 | { 924 | type Error = as Sink>::Error; 925 | 926 | #[inline] 927 | async fn send(&mut self, item: Item) -> Result<(), Self::Error> { 928 | self.inner.send(item).await 929 | } 930 | 931 | #[inline] 932 | async fn flush(&mut self) -> Result<(), Self::Error> { 933 | Sink::flush(&mut self.inner).await 934 | } 935 | 936 | #[inline] 937 | async fn close(&mut self) -> Result<(), Self::Error> { 938 | self.inner.close().await 939 | } 940 | } 941 | 942 | pub trait StreamWithCodec { 943 | type Item; 944 | 945 | fn next_with<'a>(&'a mut self, codec: &'a mut T) -> impl Future>; 946 | } 947 | 948 | pub trait SinkWithCodec 949 | where 950 | T: Encoder, 951 | { 952 | fn send_with<'a>( 953 | &'a mut self, 954 | codec: &'a mut T, 955 | item: Item, 956 | ) -> impl Future>; 957 | 958 | fn flush(&mut self) -> impl Future>; 959 | } 960 | 961 | impl StreamWithCodec 962 | for FramedRead 963 | { 964 | type Item = Result; 965 | 966 | #[inline] 967 | async fn next_with<'a>(&'a mut self, codec: &'a mut Codec) -> Option { 968 | FramedInner::next_with(&mut self.inner.io, codec, &mut self.inner.state).await 969 | } 970 | } 971 | 972 | impl StreamWithCodec for Framed { 973 | type Item = Result; 974 | 975 | #[inline] 976 | async fn next_with<'a>(&'a mut self, codec: &'a mut Codec) -> Option { 977 | FramedInner::next_with(&mut self.inner.io, codec, &mut self.inner.state).await 978 | } 979 | } 980 | 981 | impl, IO: AsyncWriteRent, AnyCodec, Item> SinkWithCodec 982 | for FramedWrite 983 | { 984 | #[inline] 985 | async fn send_with<'a>( 986 | &'a mut self, 987 | codec: &'a mut Codec, 988 | item: Item, 989 | ) -> Result<(), Codec::Error> { 990 | FramedInner::send_with(&mut self.inner.io, codec, &mut self.inner.state, item).await 991 | } 992 | 993 | #[inline] 994 | async fn flush(&mut self) -> Result<(), Codec::Error> { 995 | FramedInner::<_, (), _>::flush(&mut self.inner.io, &mut self.inner.state) 996 | .await 997 | .map_err(|e| e.into()) 998 | } 999 | } 1000 | 1001 | impl, IO: AsyncWriteRent, AnyCodec, Item> SinkWithCodec 1002 | for Framed 1003 | { 1004 | #[inline] 1005 | async fn send_with<'a>( 1006 | &'a mut self, 1007 | codec: &'a mut Codec, 1008 | item: Item, 1009 | ) -> Result<(), Codec::Error> { 1010 | FramedInner::send_with(&mut self.inner.io, codec, &mut self.inner.state, item).await 1011 | } 1012 | 1013 | #[inline] 1014 | async fn flush(&mut self) -> Result<(), Codec::Error> { 1015 | FramedInner::<_, (), _>::flush(&mut self.inner.io, &mut self.inner.state) 1016 | .await 1017 | .map_err(|e| e.into()) 1018 | } 1019 | } 1020 | 1021 | impl AsyncReadRent for Framed { 1022 | #[inline] 1023 | async fn read(&mut self, buf: T) -> BufResult { 1024 | self.inner.read(buf).await 1025 | } 1026 | 1027 | #[inline] 1028 | async fn readv(&mut self, buf: T) -> BufResult { 1029 | self.inner.readv(buf).await 1030 | } 1031 | } 1032 | 1033 | impl AsyncReadRent for FramedRead { 1034 | #[inline] 1035 | async fn read(&mut self, buf: T) -> BufResult { 1036 | self.inner.read(buf).await 1037 | } 1038 | 1039 | #[inline] 1040 | async fn readv(&mut self, buf: T) -> BufResult { 1041 | self.inner.readv(buf).await 1042 | } 1043 | } 1044 | 1045 | impl AsyncWriteRent for Framed { 1046 | #[inline] 1047 | async fn write(&mut self, buf: T) -> BufResult { 1048 | self.inner.write(buf).await 1049 | } 1050 | 1051 | #[inline] 1052 | async fn writev(&mut self, buf_vec: T) -> BufResult { 1053 | self.inner.writev(buf_vec).await 1054 | } 1055 | 1056 | #[inline] 1057 | async fn flush(&mut self) -> std::io::Result<()> { 1058 | self.inner.flush().await 1059 | } 1060 | 1061 | #[inline] 1062 | async fn shutdown(&mut self) -> std::io::Result<()> { 1063 | self.inner.shutdown().await 1064 | } 1065 | } 1066 | 1067 | impl AsyncWriteRent for FramedWrite { 1068 | #[inline] 1069 | async fn write(&mut self, buf: T) -> BufResult { 1070 | self.inner.write(buf).await 1071 | } 1072 | 1073 | #[inline] 1074 | async fn writev(&mut self, buf_vec: T) -> BufResult { 1075 | self.inner.writev(buf_vec).await 1076 | } 1077 | 1078 | #[inline] 1079 | async fn flush(&mut self) -> std::io::Result<()> { 1080 | self.inner.flush().await 1081 | } 1082 | 1083 | #[inline] 1084 | async fn shutdown(&mut self) -> std::io::Result<()> { 1085 | self.inner.shutdown().await 1086 | } 1087 | } 1088 | -------------------------------------------------------------------------------- /src/length_delimited.rs: -------------------------------------------------------------------------------- 1 | // Modified tokio's implementation to use monoio io traits natively 2 | 3 | //! Frame a stream of bytes based on a length prefix 4 | //! 5 | //! Many protocols delimit their frames by prefacing frame data with a 6 | //! frame head that specifies the length of the frame. The 7 | //! `length_delimited` module provides utilities for handling the length 8 | //! based framing. This allows the consumer to work with entire frames 9 | //! without having to worry about buffering or other framing logic. 10 | //! 11 | //! # Getting started 12 | //! 13 | //! If implementing a protocol from scratch, using length delimited framing 14 | //! is an easy way to get started. [`LengthDelimitedCodec::new()`] will 15 | //! return a length delimited codec using default configuration values. 16 | //! This can then be used to construct a framer to adapt a full-duplex 17 | //! byte stream into a stream of frames. 18 | //! 19 | //! ``` 20 | //! use monoio::io::{AsyncReadRent, AsyncWriteRent}; 21 | //! use monoio_codec::{length_delimited::LengthDelimitedCodec, Framed}; 22 | //! 23 | //! fn bind_transport(io: T) -> Framed { 24 | //! Framed::new(io, LengthDelimitedCodec::new()) 25 | //! } 26 | //! # pub fn main() {} 27 | //! ``` 28 | //! 29 | //! The returned transport implements `Sink + Stream` for `BytesMut`. It 30 | //! encodes the frame with a big-endian `u32` header denoting the frame 31 | //! payload length: 32 | //! 33 | //! ```text 34 | //! +----------+--------------------------------+ 35 | //! | len: u32 | frame payload | 36 | //! +----------+--------------------------------+ 37 | //! ``` 38 | //! 39 | //! Specifically, given the following: 40 | //! 41 | //! ``` 42 | //! use bytes::Bytes; 43 | //! use monoio::io::{sink::Sink, AsyncReadRent, AsyncWriteRent}; 44 | //! use monoio_codec::{length_delimited::LengthDelimitedCodec, Framed}; 45 | //! 46 | //! async fn write_frame(io: T) -> Result<(), Box> 47 | //! where 48 | //! T: AsyncReadRent + AsyncWriteRent + Unpin, 49 | //! { 50 | //! let mut transport = Framed::new(io, LengthDelimitedCodec::new()); 51 | //! let frame = Bytes::from("hello world"); 52 | //! 53 | //! transport.send(frame).await?; 54 | //! Ok(()) 55 | //! } 56 | //! ``` 57 | //! 58 | //! The encoded frame will look like this: 59 | //! 60 | //! ```text 61 | //! +---- len: u32 ----+---- data ----+ 62 | //! | \x00\x00\x00\x0b | hello world | 63 | //! +------------------+--------------+ 64 | //! ``` 65 | //! 66 | //! # Decoding 67 | //! 68 | //! [`FramedRead`] adapts an [`AsyncReadRent`] into a `Stream` of [`BytesMut`], 69 | //! such that each yielded [`BytesMut`] value contains the contents of an 70 | //! entire frame. There are many configuration parameters enabling 71 | //! [`FramedRead`] to handle a wide range of protocols. Here are some 72 | //! examples that will cover the various options at a high level. 73 | //! 74 | //! ## Example 1 75 | //! 76 | //! The following will parse a `u16` length field at offset 0, including the 77 | //! frame head in the yielded `BytesMut`. 78 | //! 79 | //! ``` 80 | //! # use monoio::io::AsyncReadRent; 81 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 82 | //! # fn bind_read(io: T) { 83 | //! LengthDelimitedCodec::builder() 84 | //! .length_field_offset(0) // default value 85 | //! .length_field_type::() 86 | //! .length_adjustment(0) // default value 87 | //! .num_skip(0) // Do not strip frame header 88 | //! .new_read(io); 89 | //! # } 90 | //! # pub fn main() {} 91 | //! ``` 92 | //! 93 | //! The following frame will be decoded as such: 94 | //! 95 | //! ```text 96 | //! INPUT DECODED 97 | //! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+ 98 | //! | \x00\x0B | Hello world | --> | \x00\x0B | Hello world | 99 | //! +----------+---------------+ +----------+---------------+ 100 | //! ``` 101 | //! 102 | //! The value of the length field is 11 (`\x0B`) which represents the length 103 | //! of the payload, `hello world`. By default, [`FramedRead`] assumes that 104 | //! the length field represents the number of bytes that **follows** the 105 | //! length field. Thus, the entire frame has a length of 13: 2 bytes for the 106 | //! frame head + 11 bytes for the payload. 107 | //! 108 | //! ## Example 2 109 | //! 110 | //! The following will parse a `u16` length field at offset 0, omitting the 111 | //! frame head in the yielded `BytesMut`. 112 | //! 113 | //! ``` 114 | //! # use monoio::io::AsyncReadRent; 115 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 116 | //! # fn bind_read(io: T) { 117 | //! LengthDelimitedCodec::builder() 118 | //! .length_field_offset(0) // default value 119 | //! .length_field_type::() 120 | //! .length_adjustment(0) // default value 121 | //! // `num_skip` is not needed, the default is to skip 122 | //! .new_read(io); 123 | //! # } 124 | //! # pub fn main() {} 125 | //! ``` 126 | //! 127 | //! The following frame will be decoded as such: 128 | //! 129 | //! ```text 130 | //! INPUT DECODED 131 | //! +-- len ---+--- Payload ---+ +--- Payload ---+ 132 | //! | \x00\x0B | Hello world | --> | Hello world | 133 | //! +----------+---------------+ +---------------+ 134 | //! ``` 135 | //! 136 | //! This is similar to the first example, the only difference is that the 137 | //! frame head is **not** included in the yielded `BytesMut` value. 138 | //! 139 | //! ## Example 3 140 | //! 141 | //! The following will parse a `u16` length field at offset 0, including the 142 | //! frame head in the yielded `BytesMut`. In this case, the length field 143 | //! **includes** the frame head length. 144 | //! 145 | //! ``` 146 | //! # use monoio::io::AsyncReadRent; 147 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 148 | //! # fn bind_read(io: T) { 149 | //! LengthDelimitedCodec::builder() 150 | //! .length_field_offset(0) // default value 151 | //! .length_field_type::() 152 | //! .length_adjustment(-2) // size of head 153 | //! .num_skip(0) 154 | //! .new_read(io); 155 | //! # } 156 | //! # pub fn main() {} 157 | //! ``` 158 | //! 159 | //! The following frame will be decoded as such: 160 | //! 161 | //! ```text 162 | //! INPUT DECODED 163 | //! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+ 164 | //! | \x00\x0D | Hello world | --> | \x00\x0D | Hello world | 165 | //! +----------+---------------+ +----------+---------------+ 166 | //! ``` 167 | //! 168 | //! In most cases, the length field represents the length of the payload 169 | //! only, as shown in the previous examples. However, in some protocols the 170 | //! length field represents the length of the whole frame, including the 171 | //! head. In such cases, we specify a negative `length_adjustment` to adjust 172 | //! the value provided in the frame head to represent the payload length. 173 | //! 174 | //! ## Example 4 175 | //! 176 | //! The following will parse a 3 byte length field at offset 0 in a 5 byte 177 | //! frame head, including the frame head in the yielded `BytesMut`. 178 | //! 179 | //! ``` 180 | //! # use monoio::io::AsyncReadRent; 181 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 182 | //! # fn bind_read(io: T) { 183 | //! LengthDelimitedCodec::builder() 184 | //! .length_field_offset(0) // default value 185 | //! .length_field_length(3) 186 | //! .length_adjustment(2) // remaining head 187 | //! .num_skip(0) 188 | //! .new_read(io); 189 | //! # } 190 | //! # pub fn main() {} 191 | //! ``` 192 | //! 193 | //! The following frame will be decoded as such: 194 | //! 195 | //! ```text 196 | //! INPUT 197 | //! +---- len -----+- head -+--- Payload ---+ 198 | //! | \x00\x00\x0B | \xCAFE | Hello world | 199 | //! +--------------+--------+---------------+ 200 | //! 201 | //! DECODED 202 | //! +---- len -----+- head -+--- Payload ---+ 203 | //! | \x00\x00\x0B | \xCAFE | Hello world | 204 | //! +--------------+--------+---------------+ 205 | //! ``` 206 | //! 207 | //! A more advanced example that shows a case where there is extra frame 208 | //! head data between the length field and the payload. In such cases, it is 209 | //! usually desirable to include the frame head as part of the yielded 210 | //! `BytesMut`. This lets consumers of the length delimited framer to 211 | //! process the frame head as needed. 212 | //! 213 | //! The positive `length_adjustment` value lets `FramedRead` factor in the 214 | //! additional head into the frame length calculation. 215 | //! 216 | //! ## Example 5 217 | //! 218 | //! The following will parse a `u16` length field at offset 1 of a 4 byte 219 | //! frame head. The first byte and the length field will be omitted from the 220 | //! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be 221 | //! included. 222 | //! 223 | //! ``` 224 | //! # use monoio::io::AsyncReadRent; 225 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 226 | //! # fn bind_read(io: T) { 227 | //! LengthDelimitedCodec::builder() 228 | //! .length_field_offset(1) // length of hdr1 229 | //! .length_field_type::() 230 | //! .length_adjustment(1) // length of hdr2 231 | //! .num_skip(3) // length of hdr1 + LEN 232 | //! .new_read(io); 233 | //! # } 234 | //! # pub fn main() {} 235 | //! ``` 236 | //! 237 | //! The following frame will be decoded as such: 238 | //! 239 | //! ```text 240 | //! INPUT 241 | //! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+ 242 | //! | \xCA | \x00\x0B | \xFE | Hello world | 243 | //! +--------+----------+--------+---------------+ 244 | //! 245 | //! DECODED 246 | //! +- hdr2 -+--- Payload ---+ 247 | //! | \xFE | Hello world | 248 | //! +--------+---------------+ 249 | //! ``` 250 | //! 251 | //! The length field is situated in the middle of the frame head. In this 252 | //! case, the first byte in the frame head could be a version or some other 253 | //! identifier that is not needed for processing. On the other hand, the 254 | //! second half of the head is needed. 255 | //! 256 | //! `length_field_offset` indicates how many bytes to skip before starting 257 | //! to read the length field. `length_adjustment` is the number of bytes to 258 | //! skip starting at the end of the length field. In this case, it is the 259 | //! second half of the head. 260 | //! 261 | //! ## Example 6 262 | //! 263 | //! The following will parse a `u16` length field at offset 1 of a 4 byte 264 | //! frame head. The first byte and the length field will be omitted from the 265 | //! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be 266 | //! included. In this case, the length field **includes** the frame head 267 | //! length. 268 | //! 269 | //! ``` 270 | //! # use monoio::io::AsyncReadRent; 271 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 272 | //! # fn bind_read(io: T) { 273 | //! LengthDelimitedCodec::builder() 274 | //! .length_field_offset(1) // length of hdr1 275 | //! .length_field_type::() 276 | //! .length_adjustment(-3) // length of hdr1 + LEN, negative 277 | //! .num_skip(3) 278 | //! .new_read(io); 279 | //! # } 280 | //! ``` 281 | //! 282 | //! The following frame will be decoded as such: 283 | //! 284 | //! ```text 285 | //! INPUT 286 | //! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+ 287 | //! | \xCA | \x00\x0F | \xFE | Hello world | 288 | //! +--------+----------+--------+---------------+ 289 | //! 290 | //! DECODED 291 | //! +- hdr2 -+--- Payload ---+ 292 | //! | \xFE | Hello world | 293 | //! +--------+---------------+ 294 | //! ``` 295 | //! 296 | //! Similar to the example above, the difference is that the length field 297 | //! represents the length of the entire frame instead of just the payload. 298 | //! The length of `hdr1` and `len` must be counted in `length_adjustment`. 299 | //! Note that the length of `hdr2` does **not** need to be explicitly set 300 | //! anywhere because it already is factored into the total frame length that 301 | //! is read from the byte stream. 302 | //! 303 | //! ## Example 7 304 | //! 305 | //! The following will parse a 3 byte length field at offset 0 in a 4 byte 306 | //! frame head, excluding the 4th byte from the yielded `BytesMut`. 307 | //! 308 | //! ``` 309 | //! # use monoio::io::AsyncReadRent; 310 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 311 | //! # fn bind_read(io: T) { 312 | //! LengthDelimitedCodec::builder() 313 | //! .length_field_offset(0) // default value 314 | //! .length_field_length(3) 315 | //! .length_adjustment(0) // default value 316 | //! .num_skip(4) // skip the first 4 bytes 317 | //! .new_read(io); 318 | //! # } 319 | //! # pub fn main() {} 320 | //! ``` 321 | //! 322 | //! The following frame will be decoded as such: 323 | //! 324 | //! ```text 325 | //! INPUT DECODED 326 | //! +------- len ------+--- Payload ---+ +--- Payload ---+ 327 | //! | \x00\x00\x0B\xFF | Hello world | => | Hello world | 328 | //! +------------------+---------------+ +---------------+ 329 | //! ``` 330 | //! 331 | //! A simple example where there are unused bytes between the length field 332 | //! and the payload. 333 | //! 334 | //! # Encoding 335 | //! 336 | //! [`FramedWrite`] adapts an [`AsyncWriteRent`] into a `Sink` of [`BytesMut`], 337 | //! such that each submitted [`BytesMut`] is prefaced by a length field. 338 | //! There are fewer configuration options than [`FramedRead`]. Given 339 | //! protocols that have more complex frame heads, an encoder should probably 340 | //! be written by hand using [`Encoder`]. 341 | //! 342 | //! Here is a simple example, given a `FramedWrite` with the following 343 | //! configuration: 344 | //! 345 | //! ``` 346 | //! # use monoio::io::AsyncWriteRent; 347 | //! # use monoio_codec::length_delimited::LengthDelimitedCodec; 348 | //! # fn write_frame(io: T) { 349 | //! # let _ = 350 | //! LengthDelimitedCodec::builder() 351 | //! .length_field_type::() 352 | //! .new_write(io); 353 | //! # } 354 | //! # pub fn main() {} 355 | //! ``` 356 | //! 357 | //! A payload of `hello world` will be encoded as: 358 | //! 359 | //! ```text 360 | //! +- len: u16 -+---- data ----+ 361 | //! | \x00\x0b | hello world | 362 | //! +------------+--------------+ 363 | //! ``` 364 | //! 365 | //! [`LengthDelimitedCodec::new()`]: method@LengthDelimitedCodec::new 366 | //! [`FramedRead`]: struct@FramedRead 367 | //! [`FramedWrite`]: struct@FramedWrite 368 | //! [`AsyncReadRent`]: trait@monoio::io::AsyncReadRent 369 | //! [`AsyncWriteRent`]: trait@monoio::io::AsyncWriteRent 370 | //! [`Encoder`]: trait@Encoder 371 | //! [`BytesMut`]: bytes::BytesMut 372 | 373 | use std::{ 374 | cmp, 375 | error::Error as StdError, 376 | fmt, 377 | io::{self, Cursor}, 378 | mem, 379 | }; 380 | 381 | use bytes::{Buf, BufMut, Bytes, BytesMut}; 382 | use monoio::io::{AsyncReadRent, AsyncWriteRent}; 383 | 384 | use crate::{Decoded, Decoder, Encoder, Framed, FramedRead, FramedWrite}; 385 | 386 | /// Configure length delimited `LengthDelimitedCodec`s. 387 | /// 388 | /// `Builder` enables constructing configured length delimited codecs. Note 389 | /// that not all configuration settings apply to both encoding and decoding. See 390 | /// the documentation for specific methods for more detail. 391 | #[derive(Debug, Clone, Copy)] 392 | pub struct Builder { 393 | // Maximum frame length 394 | max_frame_len: usize, 395 | 396 | // Number of bytes representing the field length 397 | length_field_len: usize, 398 | 399 | // Number of bytes in the header before the length field 400 | length_field_offset: usize, 401 | 402 | // Adjust the length specified in the header field by this amount 403 | length_adjustment: isize, 404 | 405 | // Total number of bytes to skip before reading the payload, if not set, 406 | // `length_field_len + length_field_offset` 407 | num_skip: Option, 408 | 409 | // Length field byte order (little or big endian) 410 | length_field_is_big_endian: bool, 411 | } 412 | 413 | /// An error when the number of bytes read is more than max frame length. 414 | pub struct LengthDelimitedCodecError { 415 | _priv: (), 416 | } 417 | 418 | /// A codec for frames delimited by a frame head specifying their lengths. 419 | /// 420 | /// This allows the consumer to work with entire frames without having to worry 421 | /// about buffering or other framing logic. 422 | /// 423 | /// See [module level] documentation for more detail. 424 | /// 425 | /// [module level]: index.html 426 | #[derive(Debug, Clone)] 427 | pub struct LengthDelimitedCodec { 428 | // Configuration values 429 | builder: Builder, 430 | 431 | // Read state 432 | state: DecodeState, 433 | } 434 | 435 | #[derive(Debug, Clone, Copy)] 436 | enum DecodeState { 437 | Head, 438 | Data(usize), 439 | } 440 | 441 | // ===== impl LengthDelimitedCodec ====== 442 | 443 | impl LengthDelimitedCodec { 444 | /// Creates a new `LengthDelimitedCodec` with the default configuration values. 445 | pub fn new() -> Self { 446 | Self { 447 | builder: Builder::new(), 448 | state: DecodeState::Head, 449 | } 450 | } 451 | 452 | /// Creates a new length delimited codec builder with default configuration 453 | /// values. 454 | pub fn builder() -> Builder { 455 | Builder::new() 456 | } 457 | 458 | /// Returns the current max frame setting 459 | /// 460 | /// This is the largest size this codec will accept from the wire. Larger 461 | /// frames will be rejected. 462 | pub fn max_frame_length(&self) -> usize { 463 | self.builder.max_frame_len 464 | } 465 | 466 | /// Updates the max frame setting. 467 | /// 468 | /// The change takes effect the next time a frame is decoded. In other 469 | /// words, if a frame is currently in process of being decoded with a frame 470 | /// size greater than `val` but less than the max frame length in effect 471 | /// before calling this function, then the frame will be allowed. 472 | pub fn set_max_frame_length(&mut self, val: usize) { 473 | self.builder.max_frame_length(val); 474 | } 475 | 476 | fn decode_head(&mut self, src: &mut BytesMut) -> io::Result> { 477 | let head_len = self.builder.num_head_bytes(); 478 | let field_len = self.builder.length_field_len; 479 | 480 | if src.len() < head_len { 481 | // Not enough data 482 | return Ok(Decoded::InsufficientAtLeast(head_len)); 483 | } 484 | 485 | let n = { 486 | let mut src = Cursor::new(&mut *src); 487 | 488 | // Skip the required bytes 489 | src.advance(self.builder.length_field_offset); 490 | 491 | // match endianness 492 | let n = if self.builder.length_field_is_big_endian { 493 | src.get_uint(field_len) 494 | } else { 495 | src.get_uint_le(field_len) 496 | }; 497 | 498 | if n > self.builder.max_frame_len as u64 { 499 | return Err(io::Error::new( 500 | io::ErrorKind::InvalidData, 501 | LengthDelimitedCodecError { _priv: () }, 502 | )); 503 | } 504 | 505 | // The check above ensures there is no overflow 506 | let n = n as usize; 507 | 508 | // Adjust `n` with bounds checking 509 | let n = if self.builder.length_adjustment < 0 { 510 | n.checked_sub(-self.builder.length_adjustment as usize) 511 | } else { 512 | n.checked_add(self.builder.length_adjustment as usize) 513 | }; 514 | 515 | // Error handling 516 | match n { 517 | Some(n) => n, 518 | None => { 519 | return Err(io::Error::new( 520 | io::ErrorKind::InvalidInput, 521 | "provided length would overflow after adjustment", 522 | )); 523 | } 524 | } 525 | }; 526 | 527 | let num_skip = self.builder.get_num_skip(); 528 | 529 | if num_skip > 0 { 530 | src.advance(num_skip); 531 | } 532 | 533 | // Ensure that the buffer has enough space to read the incoming 534 | // payload 535 | src.reserve(n); 536 | 537 | Ok(Decoded::Some(n)) 538 | } 539 | 540 | fn decode_data(&self, n: usize, src: &mut BytesMut) -> Decoded { 541 | // At this point, the buffer has already had the required capacity 542 | // reserved. All there is to do is read. 543 | if src.len() < n { 544 | return Decoded::InsufficientAtLeast(n); 545 | } 546 | 547 | Decoded::Some(src.split_to(n)) 548 | } 549 | } 550 | 551 | impl Decoder for LengthDelimitedCodec { 552 | type Item = BytesMut; 553 | type Error = io::Error; 554 | 555 | fn decode(&mut self, src: &mut BytesMut) -> io::Result> { 556 | let n = match self.state { 557 | DecodeState::Head => match self.decode_head(src)? { 558 | Decoded::Some(n) => { 559 | self.state = DecodeState::Data(n); 560 | n 561 | } 562 | Decoded::Insufficient => return Ok(Decoded::Insufficient), 563 | Decoded::InsufficientAtLeast(n) => return Ok(Decoded::InsufficientAtLeast(n)), 564 | }, 565 | DecodeState::Data(n) => n, 566 | }; 567 | 568 | match self.decode_data(n, src) { 569 | Decoded::Some(data) => { 570 | // Update the decode state 571 | self.state = DecodeState::Head; 572 | 573 | // Make sure the buffer has enough space to read the next head 574 | src.reserve(self.builder.num_head_bytes()); 575 | 576 | Ok(Decoded::Some(data)) 577 | } 578 | Decoded::Insufficient => Ok(Decoded::Insufficient), 579 | Decoded::InsufficientAtLeast(n) => Ok(Decoded::InsufficientAtLeast(n)), 580 | } 581 | } 582 | } 583 | 584 | impl Encoder for LengthDelimitedCodec { 585 | type Error = io::Error; 586 | 587 | fn encode(&mut self, data: Bytes, dst: &mut BytesMut) -> Result<(), io::Error> { 588 | let n = data.len(); 589 | 590 | if n > self.builder.max_frame_len { 591 | return Err(io::Error::new( 592 | io::ErrorKind::InvalidInput, 593 | LengthDelimitedCodecError { _priv: () }, 594 | )); 595 | } 596 | 597 | // Adjust `n` with bounds checking 598 | let n = if self.builder.length_adjustment < 0 { 599 | n.checked_add(-self.builder.length_adjustment as usize) 600 | } else { 601 | n.checked_sub(self.builder.length_adjustment as usize) 602 | }; 603 | 604 | let n = n.ok_or_else(|| { 605 | io::Error::new( 606 | io::ErrorKind::InvalidInput, 607 | "provided length would overflow after adjustment", 608 | ) 609 | })?; 610 | 611 | // Reserve capacity in the destination buffer to fit the frame and 612 | // length field (plus adjustment). 613 | dst.reserve(self.builder.length_field_len + n); 614 | 615 | if self.builder.length_field_is_big_endian { 616 | dst.put_uint(n as u64, self.builder.length_field_len); 617 | } else { 618 | dst.put_uint_le(n as u64, self.builder.length_field_len); 619 | } 620 | 621 | // Write the frame to the buffer 622 | dst.extend_from_slice(&data[..]); 623 | 624 | Ok(()) 625 | } 626 | } 627 | 628 | impl Default for LengthDelimitedCodec { 629 | fn default() -> Self { 630 | Self::new() 631 | } 632 | } 633 | 634 | // ===== impl Builder ===== 635 | 636 | mod builder { 637 | /// Types that can be used with `Builder::length_field_type`. 638 | pub trait LengthFieldType {} 639 | 640 | impl LengthFieldType for u8 {} 641 | impl LengthFieldType for u16 {} 642 | impl LengthFieldType for u32 {} 643 | impl LengthFieldType for u64 {} 644 | 645 | #[cfg(any( 646 | target_pointer_width = "8", 647 | target_pointer_width = "16", 648 | target_pointer_width = "32", 649 | target_pointer_width = "64", 650 | ))] 651 | impl LengthFieldType for usize {} 652 | } 653 | 654 | impl Builder { 655 | /// Creates a new length delimited codec builder with default configuration 656 | /// values. 657 | /// 658 | /// # Examples 659 | /// 660 | /// ``` 661 | /// # use monoio::io::AsyncReadRent; 662 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 663 | /// 664 | /// # fn bind_read(io: T) { 665 | /// LengthDelimitedCodec::builder() 666 | /// .length_field_offset(0) 667 | /// .length_field_type::() 668 | /// .length_adjustment(0) 669 | /// .num_skip(0) 670 | /// .new_read(io); 671 | /// # } 672 | /// # pub fn main() {} 673 | /// ``` 674 | pub fn new() -> Builder { 675 | Builder { 676 | // Default max frame length of 8MB 677 | max_frame_len: 8 * 1_024 * 1_024, 678 | 679 | // Default byte length of 4 680 | length_field_len: 4, 681 | 682 | // Default to the header field being at the start of the header. 683 | length_field_offset: 0, 684 | 685 | length_adjustment: 0, 686 | 687 | // Total number of bytes to skip before reading the payload, if not set, 688 | // `length_field_len + length_field_offset` 689 | num_skip: None, 690 | 691 | // Default to reading the length field in network (big) endian. 692 | length_field_is_big_endian: true, 693 | } 694 | } 695 | 696 | /// Read the length field as a big endian integer 697 | /// 698 | /// This is the default setting. 699 | /// 700 | /// This configuration option applies to both encoding and decoding. 701 | /// 702 | /// # Examples 703 | /// 704 | /// ``` 705 | /// # use monoio::io::AsyncReadRent; 706 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 707 | /// 708 | /// # fn bind_read(io: T) { 709 | /// LengthDelimitedCodec::builder().big_endian().new_read(io); 710 | /// # } 711 | /// # pub fn main() {} 712 | /// ``` 713 | pub fn big_endian(&mut self) -> &mut Self { 714 | self.length_field_is_big_endian = true; 715 | self 716 | } 717 | 718 | /// Read the length field as a little endian integer 719 | /// 720 | /// The default setting is big endian. 721 | /// 722 | /// This configuration option applies to both encoding and decoding. 723 | /// 724 | /// # Examples 725 | /// 726 | /// ``` 727 | /// # use monoio::io::AsyncReadRent; 728 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 729 | /// 730 | /// # fn bind_read(io: T) { 731 | /// LengthDelimitedCodec::builder().little_endian().new_read(io); 732 | /// # } 733 | /// # pub fn main() {} 734 | /// ``` 735 | pub fn little_endian(&mut self) -> &mut Self { 736 | self.length_field_is_big_endian = false; 737 | self 738 | } 739 | 740 | /// Read the length field as a native endian integer 741 | /// 742 | /// The default setting is big endian. 743 | /// 744 | /// This configuration option applies to both encoding and decoding. 745 | /// 746 | /// # Examples 747 | /// 748 | /// ``` 749 | /// # use monoio::io::AsyncReadRent; 750 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 751 | /// 752 | /// # fn bind_read(io: T) { 753 | /// LengthDelimitedCodec::builder().native_endian().new_read(io); 754 | /// # } 755 | /// # pub fn main() {} 756 | /// ``` 757 | pub fn native_endian(&mut self) -> &mut Self { 758 | if cfg!(target_endian = "big") { 759 | self.big_endian() 760 | } else { 761 | self.little_endian() 762 | } 763 | } 764 | 765 | /// Sets the max frame length in bytes 766 | /// 767 | /// This configuration option applies to both encoding and decoding. The 768 | /// default value is 8MB. 769 | /// 770 | /// When decoding, the length field read from the byte stream is checked 771 | /// against this setting **before** any adjustments are applied. When 772 | /// encoding, the length of the submitted payload is checked against this 773 | /// setting. 774 | /// 775 | /// When frames exceed the max length, an `io::Error` with the custom value 776 | /// of the `LengthDelimitedCodecError` type will be returned. 777 | /// 778 | /// # Examples 779 | /// 780 | /// ``` 781 | /// # use monoio::io::AsyncReadRent; 782 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 783 | /// 784 | /// # fn bind_read(io: T) { 785 | /// LengthDelimitedCodec::builder() 786 | /// .max_frame_length(8 * 1024 * 1024) 787 | /// .new_read(io); 788 | /// # } 789 | /// # pub fn main() {} 790 | /// ``` 791 | pub fn max_frame_length(&mut self, val: usize) -> &mut Self { 792 | self.max_frame_len = val; 793 | self 794 | } 795 | 796 | /// Sets the unsigned integer type used to represent the length field. 797 | /// 798 | /// The default type is [`u32`]. The max type is [`u64`] (or [`usize`] on 799 | /// 64-bit targets). 800 | /// 801 | /// # Examples 802 | /// 803 | /// ``` 804 | /// # use monoio::io::AsyncReadRent; 805 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 806 | /// 807 | /// # fn bind_read(io: T) { 808 | /// LengthDelimitedCodec::builder() 809 | /// .length_field_type::() 810 | /// .new_read(io); 811 | /// # } 812 | /// # pub fn main() {} 813 | /// ``` 814 | /// 815 | /// Unlike [`Builder::length_field_length`], this does not fail at runtime 816 | /// and instead produces a compile error: 817 | /// 818 | /// ```compile_fail 819 | /// # use monoio::io::AsyncReadRent; 820 | /// # use monoio_codec::length_delimited::LengthDelimitedCodec; 821 | /// # fn bind_read(io: T) { 822 | /// LengthDelimitedCodec::builder() 823 | /// .length_field_type::() 824 | /// .new_read(io); 825 | /// # } 826 | /// # pub fn main() {} 827 | /// ``` 828 | pub fn length_field_type(&mut self) -> &mut Self { 829 | self.length_field_length(mem::size_of::()) 830 | } 831 | 832 | /// Sets the number of bytes used to represent the length field 833 | /// 834 | /// The default value is `4`. The max value is `8`. 835 | /// 836 | /// This configuration option applies to both encoding and decoding. 837 | /// 838 | /// # Examples 839 | /// 840 | /// ``` 841 | /// # use monoio::io::AsyncReadRent; 842 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 843 | /// 844 | /// # fn bind_read(io: T) { 845 | /// LengthDelimitedCodec::builder() 846 | /// .length_field_length(4) 847 | /// .new_read(io); 848 | /// # } 849 | /// # pub fn main() {} 850 | /// ``` 851 | pub fn length_field_length(&mut self, val: usize) -> &mut Self { 852 | assert!(val > 0 && val <= 8, "invalid length field length"); 853 | self.length_field_len = val; 854 | self 855 | } 856 | 857 | /// Sets the number of bytes in the header before the length field 858 | /// 859 | /// This configuration option only applies to decoding. 860 | /// 861 | /// # Examples 862 | /// 863 | /// ``` 864 | /// # use monoio::io::AsyncReadRent; 865 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 866 | /// 867 | /// # fn bind_read(io: T) { 868 | /// LengthDelimitedCodec::builder() 869 | /// .length_field_offset(1) 870 | /// .new_read(io); 871 | /// # } 872 | /// # pub fn main() {} 873 | /// ``` 874 | pub fn length_field_offset(&mut self, val: usize) -> &mut Self { 875 | self.length_field_offset = val; 876 | self 877 | } 878 | 879 | /// Delta between the payload length specified in the header and the real 880 | /// payload length 881 | /// 882 | /// # Examples 883 | /// 884 | /// ``` 885 | /// # use monoio::io::AsyncReadRent; 886 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 887 | /// 888 | /// # fn bind_read(io: T) { 889 | /// LengthDelimitedCodec::builder() 890 | /// .length_adjustment(-2) 891 | /// .new_read(io); 892 | /// # } 893 | /// # pub fn main() {} 894 | /// ``` 895 | pub fn length_adjustment(&mut self, val: isize) -> &mut Self { 896 | self.length_adjustment = val; 897 | self 898 | } 899 | 900 | /// Sets the number of bytes to skip before reading the payload 901 | /// 902 | /// Default value is `length_field_len + length_field_offset` 903 | /// 904 | /// This configuration option only applies to decoding 905 | /// 906 | /// # Examples 907 | /// 908 | /// ``` 909 | /// # use monoio::io::AsyncReadRent; 910 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 911 | /// 912 | /// # fn bind_read(io: T) { 913 | /// LengthDelimitedCodec::builder().num_skip(4).new_read(io); 914 | /// # } 915 | /// # pub fn main() {} 916 | /// ``` 917 | pub fn num_skip(&mut self, val: usize) -> &mut Self { 918 | self.num_skip = Some(val); 919 | self 920 | } 921 | 922 | /// Create a configured length delimited `LengthDelimitedCodec` 923 | /// 924 | /// # Examples 925 | /// 926 | /// ``` 927 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 928 | /// # pub fn main() { 929 | /// LengthDelimitedCodec::builder() 930 | /// .length_field_offset(0) 931 | /// .length_field_type::() 932 | /// .length_adjustment(0) 933 | /// .num_skip(0) 934 | /// .new_codec(); 935 | /// # } 936 | /// ``` 937 | pub fn new_codec(&self) -> LengthDelimitedCodec { 938 | LengthDelimitedCodec { 939 | builder: *self, 940 | state: DecodeState::Head, 941 | } 942 | } 943 | 944 | /// Create a configured length delimited `FramedRead` 945 | /// 946 | /// # Examples 947 | /// 948 | /// ``` 949 | /// # use monoio::io::AsyncReadRent; 950 | /// use monoio_codec::length_delimited::LengthDelimitedCodec; 951 | /// 952 | /// # fn bind_read(io: T) { 953 | /// LengthDelimitedCodec::builder() 954 | /// .length_field_offset(0) 955 | /// .length_field_type::() 956 | /// .length_adjustment(0) 957 | /// .num_skip(0) 958 | /// .new_read(io); 959 | /// # } 960 | /// # pub fn main() {} 961 | /// ``` 962 | pub fn new_read(&self, upstream: T) -> FramedRead 963 | where 964 | T: AsyncReadRent, 965 | { 966 | FramedRead::new(upstream, self.new_codec()) 967 | } 968 | 969 | /// Create a configured length delimited `FramedWrite` 970 | /// 971 | /// # Examples 972 | /// 973 | /// ``` 974 | /// # use monoio::io::AsyncWriteRent; 975 | /// # use monoio_codec::length_delimited::LengthDelimitedCodec; 976 | /// # fn write_frame(io: T) { 977 | /// LengthDelimitedCodec::builder() 978 | /// .length_field_type::() 979 | /// .new_write(io); 980 | /// # } 981 | /// # pub fn main() {} 982 | /// ``` 983 | pub fn new_write(&self, inner: T) -> FramedWrite 984 | where 985 | T: AsyncWriteRent, 986 | { 987 | FramedWrite::new(inner, self.new_codec()) 988 | } 989 | 990 | /// Create a configured length delimited `Framed` 991 | /// 992 | /// # Examples 993 | /// 994 | /// ``` 995 | /// # use monoio::io::{AsyncReadRent, AsyncWriteRent}; 996 | /// # use monoio_codec::length_delimited::LengthDelimitedCodec; 997 | /// # fn write_frame(io: T) { 998 | /// # let _ = 999 | /// LengthDelimitedCodec::builder() 1000 | /// .length_field_type::() 1001 | /// .new_framed(io); 1002 | /// # } 1003 | /// # pub fn main() {} 1004 | /// ``` 1005 | pub fn new_framed(&self, inner: T) -> Framed 1006 | where 1007 | T: AsyncReadRent + AsyncWriteRent, 1008 | { 1009 | Framed::new(inner, self.new_codec()) 1010 | } 1011 | 1012 | fn num_head_bytes(&self) -> usize { 1013 | let num = self.length_field_offset + self.length_field_len; 1014 | cmp::max(num, self.num_skip.unwrap_or(0)) 1015 | } 1016 | 1017 | fn get_num_skip(&self) -> usize { 1018 | self.num_skip 1019 | .unwrap_or(self.length_field_offset + self.length_field_len) 1020 | } 1021 | } 1022 | 1023 | impl Default for Builder { 1024 | fn default() -> Self { 1025 | Self::new() 1026 | } 1027 | } 1028 | 1029 | // ===== impl LengthDelimitedCodecError ===== 1030 | 1031 | impl fmt::Debug for LengthDelimitedCodecError { 1032 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1033 | f.debug_struct("LengthDelimitedCodecError").finish() 1034 | } 1035 | } 1036 | 1037 | impl fmt::Display for LengthDelimitedCodecError { 1038 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1039 | f.write_str("frame size too big") 1040 | } 1041 | } 1042 | 1043 | impl StdError for LengthDelimitedCodecError {} 1044 | --------------------------------------------------------------------------------