├── .gitignore ├── Cargo.toml ├── CHANGELOG.md ├── src ├── io.rs ├── flush.rs ├── shutdown.rs ├── read.rs ├── lines.rs ├── read_to_end.rs ├── read_exact.rs ├── read_until.rs ├── split.rs ├── write_all.rs ├── allow_std.rs ├── copy.rs ├── codecs.rs ├── window.rs ├── framed_write.rs ├── framed.rs ├── framed_read.rs ├── codec.rs ├── lib.rs └── length_delimited.rs ├── LICENSE-MIT ├── .travis.yml ├── README.md ├── tests ├── codecs.rs ├── framed.rs ├── async_read.rs ├── framed_write.rs ├── framed_read.rs └── length_delimited.rs └── LICENSE-APACHE /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tokio-io" 3 | version = "0.1.4" 4 | authors = ["Alex Crichton ", "Carl Lerche "] 5 | license = "MIT/Apache-2.0" 6 | repository = "https://github.com/tokio-rs/tokio-io" 7 | homepage = "https://tokio.rs" 8 | documentation = "https://docs.rs/tokio-io/0.1" 9 | description = """ 10 | Core I/O primitives for asynchronous I/O in Rust. 11 | """ 12 | categories = ["asynchronous"] 13 | 14 | [dependencies] 15 | bytes = "0.4" 16 | futures = "0.1.11" 17 | log = "0.4" 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.1.4 (November 10, 2017) 2 | 3 | * Use `FrameTooBig` as length delimited error type (#70). 4 | * Provide `Bytes` and `Lines` codecs (#78). 5 | * Provide `AllowStdIo` wrapper (#76). 6 | 7 | # 0.1.3 (August 14, 2017) 8 | 9 | * Fix bug involving zero sized writes in copy helper (#57). 10 | * Add get / set accessors for length delimited max frame length setting. (#65). 11 | * Add `Framed::into_parts_and_codec` (#59). 12 | 13 | # 0.1.2 (May 23, 2017) 14 | 15 | * Add `from_parts` and `into_parts` to the framing combinators. 16 | * Support passing an initialized buffer to the framing combinators. 17 | * Add `length_adjustment` support to length delimited encoding (#48). 18 | 19 | # 0.1.1 (March 22, 2017) 20 | 21 | * Add some omitted `Self: Sized` bounds. 22 | * Add missing "inner" fns. 23 | 24 | # 0.1.0 (March 15, 2017) 25 | 26 | * Initial release 27 | -------------------------------------------------------------------------------- /src/io.rs: -------------------------------------------------------------------------------- 1 | //! I/O conveniences when working with primitives in `tokio-core` 2 | //! 3 | //! Contains various combinators to work with I/O objects and type definitions 4 | //! as well. 5 | //! 6 | //! A description of the high-level I/O combinators can be [found online] in 7 | //! addition to a description of the [low level details]. 8 | //! 9 | //! [found online]: https://tokio.rs/docs/getting-started/core/ 10 | //! [low level details]: https://tokio.rs/docs/going-deeper-tokio/core-low-level/ 11 | 12 | pub use allow_std::AllowStdIo; 13 | pub use copy::{copy, Copy}; 14 | pub use flush::{flush, Flush}; 15 | pub use lines::{lines, Lines}; 16 | pub use read::{read, Read}; 17 | pub use read_exact::{read_exact, ReadExact}; 18 | pub use read_to_end::{read_to_end, ReadToEnd}; 19 | pub use read_until::{read_until, ReadUntil}; 20 | pub use shutdown::{shutdown, Shutdown}; 21 | pub use split::{ReadHalf, WriteHalf}; 22 | pub use window::Window; 23 | pub use write_all::{write_all, WriteAll}; 24 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Tokio Authors 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 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | rust: 4 | - stable 5 | - beta 6 | - nightly 7 | sudo: false 8 | before_script: 9 | - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH 10 | script: 11 | - cargo build 12 | - cargo test 13 | - cargo test --no-default-features 14 | - cargo doc --no-deps 15 | 16 | after_success: 17 | - travis-cargo --only nightly doc-upload 18 | env: 19 | global: 20 | - secure: "aDOBmkUbJR3kY1EDzchDhxdzV2HBt8yUHicNlWDZUh+JOmeV/2ezqPt4bre2fgludm98P7tmTG7GHbtnYtMaU4MTw8EarmEXR3tXqUQdDoWzSsMbUsJVZp3wRUWEF2UUZMv7u+xsvSDrIwF2ux6LcySEN6j2gmlobphmOod5NzhJp8d4ap7yLZ6UW4cnJ3m69HtD4yYa8wy3kGvfYOgcFBoB1HODSu2J9sFCzVrdxe9tm3aBvvl/dR0RAmRXyM7ZNE8Fv6aiISJ91M3EaulN1jzggdYEkN3bU0oxnzHvzrFDt1zmi30uR8jBYJmbBlSKYnhSoQqCKZMS7QEATqMDxGl1/M8QJPnaKg+Hu3w0i5yH5QInLW/8j+myzhMzLM8/IDrppZS4fuEb1XcJ/5m+ip3XjLSrXQzFRioA908NvcOUL5t71Yx1uey2kSccUOsGh3wETRbSWWs5SQPxt4BYP9jd8zpVZIInJRgztLFwqGcTDdDSrVHpKpzVNJSMmdgOG8lNubGjdwyrC8J2EyPlWa+QOyx7CoSoyygm4nV4a/UpGPeNgHHkbj/qrf3dhueypLnlj8nJyBk2Lzug8PVCszyCwfv2wXVJ9OCO40lp01XTvxT0cLzgWinn+TvmRn+Mhyt13u2urLjqfjKjA93v6OGZUqnvDG+2FiwGNP3GS+E=" 21 | 22 | notifications: 23 | email: 24 | on_success: never 25 | -------------------------------------------------------------------------------- /src/flush.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | use futures::{Poll, Future, Async}; 4 | 5 | use AsyncWrite; 6 | 7 | /// A future used to fully flush an I/O object. 8 | /// 9 | /// Resolves to the underlying I/O object once the flush operation is complete. 10 | /// 11 | /// Created by the [`flush`] function. 12 | /// 13 | /// [`flush`]: fn.flush.html 14 | #[derive(Debug)] 15 | pub struct Flush { 16 | a: Option, 17 | } 18 | 19 | /// Creates a future which will entirely flush an I/O object and then yield the 20 | /// object itself. 21 | /// 22 | /// This function will consume the object provided if an error happens, and 23 | /// otherwise it will repeatedly call `flush` until it sees `Ok(())`, scheduling 24 | /// a retry if `WouldBlock` is seen along the way. 25 | pub fn flush(a: A) -> Flush 26 | where A: AsyncWrite, 27 | { 28 | Flush { 29 | a: Some(a), 30 | } 31 | } 32 | 33 | impl Future for Flush 34 | where A: AsyncWrite, 35 | { 36 | type Item = A; 37 | type Error = io::Error; 38 | 39 | fn poll(&mut self) -> Poll { 40 | try_nb!(self.a.as_mut().unwrap().flush()); 41 | Ok(Async::Ready(self.a.take().unwrap())) 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/shutdown.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | use futures::{Poll, Future, Async}; 4 | 5 | use AsyncWrite; 6 | 7 | /// A future used to fully shutdown an I/O object. 8 | /// 9 | /// Resolves to the underlying I/O object once the shutdown operation is 10 | /// complete. 11 | /// 12 | /// Created by the [`shutdown`] function. 13 | /// 14 | /// [`shutdown`]: fn.shutdown.html 15 | #[derive(Debug)] 16 | pub struct Shutdown { 17 | a: Option, 18 | } 19 | 20 | /// Creates a future which will entirely shutdown an I/O object and then yield 21 | /// the object itself. 22 | /// 23 | /// This function will consume the object provided if an error happens, and 24 | /// otherwise it will repeatedly call `shutdown` until it sees `Ok(())`, 25 | /// scheduling a retry if `WouldBlock` is seen along the way. 26 | pub fn shutdown(a: A) -> Shutdown 27 | where A: AsyncWrite, 28 | { 29 | Shutdown { 30 | a: Some(a), 31 | } 32 | } 33 | 34 | impl Future for Shutdown 35 | where A: AsyncWrite, 36 | { 37 | type Item = A; 38 | type Error = io::Error; 39 | 40 | fn poll(&mut self) -> Poll { 41 | try_nb!(self.a.as_mut().unwrap().shutdown()); 42 | Ok(Async::Ready(self.a.take().unwrap())) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## The tokio-io crate has been moved into the [tokio](https://github.com/tokio-rs/tokio) Git repository. 2 | 3 | Do not use this repo anymore. 4 | 5 | # tokio-io 6 | 7 | Core I/O abstractions for the Tokio stack. 8 | 9 | [![Build Status](https://travis-ci.org/tokio-rs/tokio-io.svg?branch=master)](https://travis-ci.org/tokio-rs/tokio-io) 10 | 11 | [Documentation](https://docs.rs/tokio-io) 12 | 13 | ## Usage 14 | 15 | First, add this to your `Cargo.toml`: 16 | 17 | ```toml 18 | [dependencies] 19 | tokio-io = "0.1" 20 | ``` 21 | 22 | Next, add this to your crate: 23 | 24 | ```rust 25 | extern crate tokio_io; 26 | ``` 27 | 28 | You can find extensive documentation and examples about how to use this crate 29 | online at [https://tokio.rs](https://tokio.rs). The [API 30 | documentation](https://docs.rs/tokio-io) is also a great place to get started 31 | for the nitty-gritty. 32 | 33 | 34 | # License 35 | 36 | This project is licensed under either of 37 | 38 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 39 | http://www.apache.org/licenses/LICENSE-2.0) 40 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or 41 | http://opensource.org/licenses/MIT) 42 | 43 | at your option. 44 | 45 | ### Contribution 46 | 47 | Unless you explicitly state otherwise, any contribution intentionally submitted 48 | for inclusion in Tokio by you, as defined in the Apache-2.0 license, shall be 49 | dual licensed as above, without any additional terms or conditions. 50 | -------------------------------------------------------------------------------- /src/read.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::mem; 3 | 4 | use futures::{Future, Poll}; 5 | 6 | use AsyncRead; 7 | 8 | #[derive(Debug)] 9 | enum State { 10 | Pending { 11 | rd: R, 12 | buf: T, 13 | }, 14 | Empty, 15 | } 16 | 17 | /// Tries to read some bytes directly into the given `buf` in asynchronous 18 | /// manner, returning a future type. 19 | /// 20 | /// The returned future will resolve to both the I/O stream and the buffer 21 | /// as well as the number of bytes read once the read operation is completed. 22 | pub fn read(rd: R, buf: T) -> Read 23 | where R: AsyncRead, 24 | T: AsMut<[u8]> 25 | { 26 | Read { state: State::Pending { rd: rd, buf: buf } } 27 | } 28 | 29 | /// A future which can be used to easily read available number of bytes to fill 30 | /// a buffer. 31 | /// 32 | /// Created by the [`read`] function. 33 | #[derive(Debug)] 34 | pub struct Read { 35 | state: State, 36 | } 37 | 38 | impl Future for Read 39 | where R: AsyncRead, 40 | T: AsMut<[u8]> 41 | { 42 | type Item = (R, T, usize); 43 | type Error = io::Error; 44 | 45 | fn poll(&mut self) -> Poll<(R, T, usize), io::Error> { 46 | let nread = match self.state { 47 | State::Pending { ref mut rd, ref mut buf } => try_nb!(rd.read(&mut buf.as_mut()[..])), 48 | State::Empty => panic!("poll a Read after it's done"), 49 | }; 50 | 51 | match mem::replace(&mut self.state, State::Empty) { 52 | State::Pending { rd, buf } => Ok((rd, buf, nread).into()), 53 | State::Empty => panic!("invalid internal state"), 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/lines.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, BufRead}; 2 | use std::mem; 3 | 4 | use futures::{Poll, Stream}; 5 | 6 | use AsyncRead; 7 | 8 | /// Combinator created by the top-level `lines` method which is a stream over 9 | /// the lines of text on an I/O object. 10 | #[derive(Debug)] 11 | pub struct Lines { 12 | io: A, 13 | line: String, 14 | } 15 | 16 | /// Creates a new stream from the I/O object given representing the lines of 17 | /// input that are found on `A`. 18 | /// 19 | /// This method takes an asynchronous I/O object, `a`, and returns a `Stream` of 20 | /// lines that the object contains. The returned stream will reach its end once 21 | /// `a` reaches EOF. 22 | pub fn lines(a: A) -> Lines 23 | where A: AsyncRead + BufRead, 24 | { 25 | Lines { 26 | io: a, 27 | line: String::new(), 28 | } 29 | } 30 | 31 | impl Lines { 32 | /// Returns the underlying I/O object. 33 | /// 34 | /// Note that this may lose data already read into internal buffers. It's 35 | /// recommended to only call this once the stream has reached its end. 36 | pub fn into_inner(self) -> A { 37 | self.io 38 | } 39 | } 40 | 41 | impl Stream for Lines 42 | where A: AsyncRead + BufRead, 43 | { 44 | type Item = String; 45 | type Error = io::Error; 46 | 47 | fn poll(&mut self) -> Poll, io::Error> { 48 | let n = try_nb!(self.io.read_line(&mut self.line)); 49 | if n == 0 && self.line.len() == 0 { 50 | return Ok(None.into()) 51 | } 52 | if self.line.ends_with("\n") { 53 | self.line.pop(); 54 | if self.line.ends_with("\r") { 55 | self.line.pop(); 56 | } 57 | } 58 | Ok(Some(mem::replace(&mut self.line, String::new())).into()) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/read_to_end.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::mem; 3 | 4 | use futures::{Poll, Future}; 5 | 6 | use AsyncRead; 7 | 8 | /// A future which can be used to easily read the entire contents of a stream 9 | /// into a vector. 10 | /// 11 | /// Created by the [`read_to_end`] function. 12 | /// 13 | /// [`read_to_end`]: fn.read_to_end.html 14 | #[derive(Debug)] 15 | pub struct ReadToEnd { 16 | state: State, 17 | } 18 | 19 | #[derive(Debug)] 20 | enum State { 21 | Reading { 22 | a: A, 23 | buf: Vec, 24 | }, 25 | Empty, 26 | } 27 | 28 | /// Creates a future which will read all the bytes associated with the I/O 29 | /// object `A` into the buffer provided. 30 | /// 31 | /// In the case of an error the buffer and the object will be discarded, with 32 | /// the error yielded. In the case of success the object will be destroyed and 33 | /// the buffer will be returned, with all data read from the stream appended to 34 | /// the buffer. 35 | pub fn read_to_end(a: A, buf: Vec) -> ReadToEnd 36 | where A: AsyncRead, 37 | { 38 | ReadToEnd { 39 | state: State::Reading { 40 | a: a, 41 | buf: buf, 42 | } 43 | } 44 | } 45 | 46 | impl Future for ReadToEnd 47 | where A: AsyncRead, 48 | { 49 | type Item = (A, Vec); 50 | type Error = io::Error; 51 | 52 | fn poll(&mut self) -> Poll<(A, Vec), io::Error> { 53 | match self.state { 54 | State::Reading { ref mut a, ref mut buf } => { 55 | // If we get `Ok`, then we know the stream hit EOF and we're done. If we 56 | // hit "would block" then all the read data so far is in our buffer, and 57 | // otherwise we propagate errors 58 | try_nb!(a.read_to_end(buf)); 59 | }, 60 | State::Empty => panic!("poll ReadToEnd after it's done"), 61 | } 62 | 63 | match mem::replace(&mut self.state, State::Empty) { 64 | State::Reading { a, buf } => Ok((a, buf).into()), 65 | State::Empty => unreachable!(), 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/read_exact.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::mem; 3 | 4 | use futures::{Poll, Future}; 5 | 6 | use AsyncRead; 7 | 8 | /// A future which can be used to easily read exactly enough bytes to fill 9 | /// a buffer. 10 | /// 11 | /// Created by the [`read_exact`] function. 12 | /// 13 | /// [`read_exact`]: fn.read_exact.html 14 | #[derive(Debug)] 15 | pub struct ReadExact { 16 | state: State, 17 | } 18 | 19 | #[derive(Debug)] 20 | enum State { 21 | Reading { 22 | a: A, 23 | buf: T, 24 | pos: usize, 25 | }, 26 | Empty, 27 | } 28 | 29 | /// Creates a future which will read exactly enough bytes to fill `buf`, 30 | /// returning an error if EOF is hit sooner. 31 | /// 32 | /// The returned future will resolve to both the I/O stream as well as the 33 | /// buffer once the read operation is completed. 34 | /// 35 | /// In the case of an error the buffer and the object will be discarded, with 36 | /// the error yielded. In the case of success the object will be destroyed and 37 | /// the buffer will be returned, with all data read from the stream appended to 38 | /// the buffer. 39 | pub fn read_exact(a: A, buf: T) -> ReadExact 40 | where A: AsyncRead, 41 | T: AsMut<[u8]>, 42 | { 43 | ReadExact { 44 | state: State::Reading { 45 | a: a, 46 | buf: buf, 47 | pos: 0, 48 | }, 49 | } 50 | } 51 | 52 | fn eof() -> io::Error { 53 | io::Error::new(io::ErrorKind::UnexpectedEof, "early eof") 54 | } 55 | 56 | impl Future for ReadExact 57 | where A: AsyncRead, 58 | T: AsMut<[u8]>, 59 | { 60 | type Item = (A, T); 61 | type Error = io::Error; 62 | 63 | fn poll(&mut self) -> Poll<(A, T), io::Error> { 64 | match self.state { 65 | State::Reading { ref mut a, ref mut buf, ref mut pos } => { 66 | let buf = buf.as_mut(); 67 | while *pos < buf.len() { 68 | let n = try_nb!(a.read(&mut buf[*pos..])); 69 | *pos += n; 70 | if n == 0 { 71 | return Err(eof()) 72 | } 73 | } 74 | } 75 | State::Empty => panic!("poll a ReadExact after it's done"), 76 | } 77 | 78 | match mem::replace(&mut self.state, State::Empty) { 79 | State::Reading { a, buf, .. } => Ok((a, buf).into()), 80 | State::Empty => panic!(), 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/read_until.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, BufRead}; 2 | use std::mem; 3 | 4 | use futures::{Poll, Future}; 5 | 6 | use AsyncRead; 7 | 8 | /// A future which can be used to easily read the contents of a stream into a 9 | /// vector until the delimiter is reached. 10 | /// 11 | /// Created by the [`read_until`] function. 12 | /// 13 | /// [`read_until`]: fn.read_until.html 14 | #[derive(Debug)] 15 | pub struct ReadUntil { 16 | state: State, 17 | } 18 | 19 | #[derive(Debug)] 20 | enum State { 21 | Reading { 22 | a: A, 23 | byte: u8, 24 | buf: Vec, 25 | }, 26 | Empty, 27 | } 28 | 29 | /// Creates a future which will read all the bytes associated with the I/O 30 | /// object `A` into the buffer provided until the delimiter `byte` is reached. 31 | /// This method is the async equivalent to [`BufRead::read_until`]. 32 | /// 33 | /// In case of an error the buffer and the object will be discarded, with 34 | /// the error yielded. In the case of success the object will be destroyed and 35 | /// the buffer will be returned, with all bytes up to, and including, the delimiter 36 | /// (if found). 37 | /// 38 | /// [`BufRead::read_until`]: https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_until 39 | pub fn read_until(a: A, byte: u8, buf: Vec) -> ReadUntil 40 | where A: AsyncRead + BufRead, 41 | { 42 | ReadUntil { 43 | state: State::Reading { 44 | a: a, 45 | byte: byte, 46 | buf: buf, 47 | } 48 | } 49 | } 50 | 51 | impl Future for ReadUntil 52 | where A: AsyncRead + BufRead 53 | { 54 | type Item = (A, Vec); 55 | type Error = io::Error; 56 | 57 | fn poll(&mut self) -> Poll<(A, Vec), io::Error> { 58 | match self.state { 59 | State::Reading { ref mut a, byte, ref mut buf } => { 60 | // If we get `Ok(n)`, then we know the stream hit EOF or the delimiter. 61 | // and just return it, as we are finished. 62 | // If we hit "would block" then all the read data so far 63 | // is in our buffer, and otherwise we propagate errors. 64 | try_nb!(a.read_until(byte, buf)); 65 | }, 66 | State::Empty => panic!("poll ReadUntil after it's done"), 67 | } 68 | 69 | match mem::replace(&mut self.state, State::Empty) { 70 | State::Reading { a, byte: _, buf } => Ok((a, buf).into()), 71 | State::Empty => unreachable!(), 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/split.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Read, Write}; 2 | 3 | use futures::{Async, Poll}; 4 | use futures::sync::BiLock; 5 | use bytes::{Buf, BufMut}; 6 | 7 | use {AsyncRead, AsyncWrite}; 8 | 9 | /// The readable half of an object returned from `AsyncRead::split`. 10 | #[derive(Debug)] 11 | pub struct ReadHalf { 12 | handle: BiLock, 13 | } 14 | 15 | /// The writable half of an object returned from `AsyncRead::split`. 16 | #[derive(Debug)] 17 | pub struct WriteHalf { 18 | handle: BiLock, 19 | } 20 | 21 | pub fn split(t: T) -> (ReadHalf, WriteHalf) { 22 | let (a, b) = BiLock::new(t); 23 | (ReadHalf { handle: a }, WriteHalf { handle: b }) 24 | } 25 | 26 | fn would_block() -> io::Error { 27 | io::Error::new(io::ErrorKind::WouldBlock, "would block") 28 | } 29 | 30 | impl Read for ReadHalf { 31 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 32 | match self.handle.poll_lock() { 33 | Async::Ready(mut l) => l.read(buf), 34 | Async::NotReady => Err(would_block()), 35 | } 36 | } 37 | } 38 | 39 | impl AsyncRead for ReadHalf { 40 | fn read_buf(&mut self, buf: &mut B) -> Poll { 41 | match self.handle.poll_lock() { 42 | Async::Ready(mut l) => l.read_buf(buf), 43 | Async::NotReady => Err(would_block()), 44 | } 45 | } 46 | } 47 | 48 | impl Write for WriteHalf { 49 | fn write(&mut self, buf: &[u8]) -> io::Result { 50 | match self.handle.poll_lock() { 51 | Async::Ready(mut l) => l.write(buf), 52 | Async::NotReady => Err(would_block()), 53 | } 54 | } 55 | 56 | fn flush(&mut self) -> io::Result<()> { 57 | match self.handle.poll_lock() { 58 | Async::Ready(mut l) => l.flush(), 59 | Async::NotReady => Err(would_block()), 60 | } 61 | } 62 | } 63 | 64 | impl AsyncWrite for WriteHalf { 65 | fn shutdown(&mut self) -> Poll<(), io::Error> { 66 | match self.handle.poll_lock() { 67 | Async::Ready(mut l) => l.shutdown(), 68 | Async::NotReady => Err(would_block()), 69 | } 70 | } 71 | 72 | fn write_buf(&mut self, buf: &mut B) -> Poll 73 | where Self: Sized, 74 | { 75 | match self.handle.poll_lock() { 76 | Async::Ready(mut l) => l.write_buf(buf), 77 | Async::NotReady => Err(would_block()), 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/write_all.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::mem; 3 | 4 | use futures::{Poll, Future}; 5 | 6 | use AsyncWrite; 7 | 8 | /// A future used to write the entire contents of some data to a stream. 9 | /// 10 | /// This is created by the [`write_all`] top-level method. 11 | /// 12 | /// [`write_all`]: fn.write_all.html 13 | #[derive(Debug)] 14 | pub struct WriteAll { 15 | state: State, 16 | } 17 | 18 | #[derive(Debug)] 19 | enum State { 20 | Writing { 21 | a: A, 22 | buf: T, 23 | pos: usize, 24 | }, 25 | Empty, 26 | } 27 | 28 | /// Creates a future that will write the entire contents of the buffer `buf` to 29 | /// the stream `a` provided. 30 | /// 31 | /// The returned future will not return until all the data has been written, and 32 | /// the future will resolve to the stream as well as the buffer (for reuse if 33 | /// needed). 34 | /// 35 | /// Any error which happens during writing will cause both the stream and the 36 | /// buffer to get destroyed. 37 | /// 38 | /// The `buf` parameter here only requires the `AsRef<[u8]>` trait, which should 39 | /// be broadly applicable to accepting data which can be converted to a slice. 40 | /// The `Window` struct is also available in this crate to provide a different 41 | /// window into a slice if necessary. 42 | pub fn write_all(a: A, buf: T) -> WriteAll 43 | where A: AsyncWrite, 44 | T: AsRef<[u8]>, 45 | { 46 | WriteAll { 47 | state: State::Writing { 48 | a: a, 49 | buf: buf, 50 | pos: 0, 51 | }, 52 | } 53 | } 54 | 55 | fn zero_write() -> io::Error { 56 | io::Error::new(io::ErrorKind::WriteZero, "zero-length write") 57 | } 58 | 59 | impl Future for WriteAll 60 | where A: AsyncWrite, 61 | T: AsRef<[u8]>, 62 | { 63 | type Item = (A, T); 64 | type Error = io::Error; 65 | 66 | fn poll(&mut self) -> Poll<(A, T), io::Error> { 67 | match self.state { 68 | State::Writing { ref mut a, ref buf, ref mut pos } => { 69 | let buf = buf.as_ref(); 70 | while *pos < buf.len() { 71 | let n = try_nb!(a.write(&buf[*pos..])); 72 | *pos += n; 73 | if n == 0 { 74 | return Err(zero_write()) 75 | } 76 | } 77 | } 78 | State::Empty => panic!("poll a WriteAll after it's done"), 79 | } 80 | 81 | match mem::replace(&mut self.state, State::Empty) { 82 | State::Writing { a, buf, .. } => Ok((a, buf).into()), 83 | State::Empty => panic!(), 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/codecs.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio_io; 2 | extern crate bytes; 3 | 4 | use bytes::{BytesMut, Bytes, BufMut}; 5 | use tokio_io::codec::{BytesCodec, LinesCodec, Decoder, Encoder}; 6 | 7 | #[test] 8 | fn bytes_decoder() { 9 | let mut codec = BytesCodec::new(); 10 | let buf = &mut BytesMut::new(); 11 | buf.put_slice(b"abc"); 12 | assert_eq!("abc", codec.decode(buf).unwrap().unwrap()); 13 | assert_eq!(None, codec.decode(buf).unwrap()); 14 | assert_eq!(None, codec.decode(buf).unwrap()); 15 | buf.put_slice(b"a"); 16 | assert_eq!("a", codec.decode(buf).unwrap().unwrap()); 17 | } 18 | 19 | #[test] 20 | fn bytes_encoder() { 21 | let mut codec = BytesCodec::new(); 22 | 23 | // Default capacity of BytesMut 24 | #[cfg(target_pointer_width = "64")] 25 | const INLINE_CAP: usize = 4 * 8 - 1; 26 | #[cfg(target_pointer_width = "32")] 27 | const INLINE_CAP: usize = 4 * 4 - 1; 28 | 29 | let mut buf = BytesMut::new(); 30 | codec.encode(Bytes::from_static(&[0; INLINE_CAP + 1]), &mut buf).unwrap(); 31 | 32 | // Default capacity of Framed Read 33 | const INITIAL_CAPACITY: usize = 8 * 1024; 34 | 35 | let mut buf = BytesMut::with_capacity(INITIAL_CAPACITY); 36 | codec.encode(Bytes::from_static(&[0; INITIAL_CAPACITY + 1]), &mut buf).unwrap(); 37 | } 38 | 39 | #[test] 40 | fn lines_decoder() { 41 | let mut codec = LinesCodec::new(); 42 | let buf = &mut BytesMut::new(); 43 | buf.reserve(200); 44 | buf.put("line 1\nline 2\r\nline 3\n\r\n\r"); 45 | assert_eq!("line 1", codec.decode(buf).unwrap().unwrap()); 46 | assert_eq!("line 2", codec.decode(buf).unwrap().unwrap()); 47 | assert_eq!("line 3", codec.decode(buf).unwrap().unwrap()); 48 | assert_eq!("", codec.decode(buf).unwrap().unwrap()); 49 | assert_eq!(None, codec.decode(buf).unwrap()); 50 | assert_eq!(None, codec.decode_eof(buf).unwrap()); 51 | buf.put("k"); 52 | assert_eq!(None, codec.decode(buf).unwrap()); 53 | assert_eq!("\rk", codec.decode_eof(buf).unwrap().unwrap()); 54 | assert_eq!(None, codec.decode(buf).unwrap()); 55 | assert_eq!(None, codec.decode_eof(buf).unwrap()); 56 | } 57 | 58 | #[test] 59 | fn lines_encoder() { 60 | let mut codec = BytesCodec::new(); 61 | 62 | // Default capacity of BytesMut 63 | #[cfg(target_pointer_width = "64")] 64 | const INLINE_CAP: usize = 4 * 8 - 1; 65 | #[cfg(target_pointer_width = "32")] 66 | const INLINE_CAP: usize = 4 * 4 - 1; 67 | 68 | let mut buf = BytesMut::new(); 69 | codec.encode(Bytes::from_static(&[b'a'; INLINE_CAP + 1]), &mut buf).unwrap(); 70 | 71 | // Default capacity of Framed Read 72 | const INITIAL_CAPACITY: usize = 8 * 1024; 73 | 74 | let mut buf = BytesMut::with_capacity(INITIAL_CAPACITY); 75 | codec.encode(Bytes::from_static(&[b'a'; INITIAL_CAPACITY + 1]), &mut buf).unwrap(); 76 | } 77 | -------------------------------------------------------------------------------- /tests/framed.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio_io; 2 | extern crate bytes; 3 | extern crate futures; 4 | 5 | use futures::{Stream, Future}; 6 | use std::io::{self, Read}; 7 | use tokio_io::codec::{Framed, FramedParts, Decoder, Encoder}; 8 | use tokio_io::AsyncRead; 9 | use bytes::{BytesMut, Buf, BufMut, IntoBuf, BigEndian}; 10 | 11 | const INITIAL_CAPACITY: usize = 8 * 1024; 12 | 13 | struct U32Codec; 14 | 15 | impl Decoder for U32Codec { 16 | type Item = u32; 17 | type Error = io::Error; 18 | 19 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 20 | if buf.len() < 4 { 21 | return Ok(None); 22 | } 23 | 24 | let n = buf.split_to(4).into_buf().get_u32::(); 25 | Ok(Some(n)) 26 | } 27 | } 28 | 29 | impl Encoder for U32Codec { 30 | type Item = u32; 31 | type Error = io::Error; 32 | 33 | fn encode(&mut self, item: u32, dst: &mut BytesMut) -> io::Result<()> { 34 | // Reserve space 35 | dst.reserve(4); 36 | dst.put_u32::(item); 37 | Ok(()) 38 | } 39 | } 40 | 41 | struct DontReadIntoThis; 42 | 43 | impl Read for DontReadIntoThis { 44 | fn read(&mut self, _: &mut [u8]) -> io::Result { 45 | Err(io::Error::new(io::ErrorKind::Other, 46 | "Read into something you weren't supposed to.")) 47 | } 48 | } 49 | 50 | impl AsyncRead for DontReadIntoThis {} 51 | 52 | #[test] 53 | fn can_read_from_existing_buf() { 54 | let parts = FramedParts { 55 | inner: DontReadIntoThis, 56 | readbuf: vec![0, 0, 0, 42].into(), 57 | writebuf: BytesMut::with_capacity(0), 58 | }; 59 | let framed = Framed::from_parts(parts, U32Codec); 60 | 61 | let num = framed 62 | .into_future() 63 | .map(|(first_num, _)| { 64 | first_num.unwrap() 65 | }) 66 | .wait() 67 | .map_err(|e| e.0) 68 | .unwrap(); 69 | assert_eq!(num, 42); 70 | } 71 | 72 | #[test] 73 | fn external_buf_grows_to_init() { 74 | let parts = FramedParts { 75 | inner: DontReadIntoThis, 76 | readbuf: vec![0, 0, 0, 42].into(), 77 | writebuf: BytesMut::with_capacity(0), 78 | }; 79 | let framed = Framed::from_parts(parts, U32Codec); 80 | let FramedParts { readbuf, .. } = framed.into_parts(); 81 | 82 | assert_eq!(readbuf.capacity(), INITIAL_CAPACITY); 83 | } 84 | 85 | #[test] 86 | fn external_buf_does_not_shrink() { 87 | let parts = FramedParts { 88 | inner: DontReadIntoThis, 89 | readbuf: vec![0; INITIAL_CAPACITY * 2].into(), 90 | writebuf: BytesMut::with_capacity(0), 91 | }; 92 | let framed = Framed::from_parts(parts, U32Codec); 93 | let FramedParts { readbuf, .. } = framed.into_parts(); 94 | 95 | assert_eq!(readbuf.capacity(), INITIAL_CAPACITY * 2); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/allow_std.rs: -------------------------------------------------------------------------------- 1 | use {AsyncRead, AsyncWrite}; 2 | use futures::{Async, Poll}; 3 | use std::{fmt, io}; 4 | 5 | /// A simple wrapper type which allows types which implement only 6 | /// implement `std::io::Read` or `std::io::Write` 7 | /// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`. 8 | /// 9 | /// If these types issue an error with the kind `io::ErrorKind::WouldBlock`, 10 | /// it is expected that they will notify the current task on readiness. 11 | /// Synchronous `std` types should not issue errors of this kind and 12 | /// are safe to use in this context. However, using these types with 13 | /// `AllowStdIo` will cause the event loop to block, so they should be used 14 | /// with care. 15 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 16 | pub struct AllowStdIo(T); 17 | 18 | impl AllowStdIo { 19 | /// Creates a new `AllowStdIo` from an existing IO object. 20 | pub fn new(io: T) -> Self { 21 | AllowStdIo(io) 22 | } 23 | 24 | /// Returns a reference to the contained IO object. 25 | pub fn get_ref(&self) -> &T { 26 | &self.0 27 | } 28 | 29 | /// Returns a mutable reference to the contained IO object. 30 | pub fn get_mut(&mut self) -> &mut T { 31 | &mut self.0 32 | } 33 | 34 | /// Consumes self and returns the contained IO object. 35 | pub fn into_inner(self) -> T { 36 | self.0 37 | } 38 | } 39 | 40 | impl io::Write for AllowStdIo where T: io::Write { 41 | fn write(&mut self, buf: &[u8]) -> io::Result { 42 | self.0.write(buf) 43 | } 44 | fn flush(&mut self) -> io::Result<()> { 45 | self.0.flush() 46 | } 47 | fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { 48 | self.0.write_all(buf) 49 | } 50 | fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { 51 | self.0.write_fmt(fmt) 52 | } 53 | } 54 | 55 | impl AsyncWrite for AllowStdIo where T: io::Write { 56 | fn shutdown(&mut self) -> Poll<(), io::Error> { 57 | Ok(Async::Ready(())) 58 | } 59 | } 60 | 61 | impl io::Read for AllowStdIo where T: io::Read { 62 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 63 | self.0.read(buf) 64 | } 65 | // TODO: implement the `initializer` fn when it stabilizes. 66 | // See rust-lang/rust #42788 67 | fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { 68 | self.0.read_to_end(buf) 69 | } 70 | fn read_to_string(&mut self, buf: &mut String) -> io::Result { 71 | self.0.read_to_string(buf) 72 | } 73 | fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { 74 | self.0.read_exact(buf) 75 | } 76 | } 77 | 78 | impl AsyncRead for AllowStdIo where T: io::Read { 79 | // TODO: override prepare_unitialized_buffer once `Read::initializer` is stable. 80 | // See rust-lang/rust #42788 81 | } 82 | -------------------------------------------------------------------------------- /src/copy.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | use futures::{Future, Poll}; 4 | 5 | use {AsyncRead, AsyncWrite}; 6 | 7 | /// A future which will copy all data from a reader into a writer. 8 | /// 9 | /// Created by the [`copy`] function, this future will resolve to the number of 10 | /// bytes copied or an error if one happens. 11 | /// 12 | /// [`copy`]: fn.copy.html 13 | #[derive(Debug)] 14 | pub struct Copy { 15 | reader: Option, 16 | read_done: bool, 17 | writer: Option, 18 | pos: usize, 19 | cap: usize, 20 | amt: u64, 21 | buf: Box<[u8]>, 22 | } 23 | 24 | /// Creates a future which represents copying all the bytes from one object to 25 | /// another. 26 | /// 27 | /// The returned future will copy all the bytes read from `reader` into the 28 | /// `writer` specified. This future will only complete once the `reader` has hit 29 | /// EOF and all bytes have been written to and flushed from the `writer` 30 | /// provided. 31 | /// 32 | /// On success the number of bytes is returned and the `reader` and `writer` are 33 | /// consumed. On error the error is returned and the I/O objects are consumed as 34 | /// well. 35 | pub fn copy(reader: R, writer: W) -> Copy 36 | where R: AsyncRead, 37 | W: AsyncWrite, 38 | { 39 | Copy { 40 | reader: Some(reader), 41 | read_done: false, 42 | writer: Some(writer), 43 | amt: 0, 44 | pos: 0, 45 | cap: 0, 46 | buf: Box::new([0; 2048]), 47 | } 48 | } 49 | 50 | impl Future for Copy 51 | where R: AsyncRead, 52 | W: AsyncWrite, 53 | { 54 | type Item = (u64, R, W); 55 | type Error = io::Error; 56 | 57 | fn poll(&mut self) -> Poll<(u64, R, W), io::Error> { 58 | loop { 59 | // If our buffer is empty, then we need to read some data to 60 | // continue. 61 | if self.pos == self.cap && !self.read_done { 62 | let reader = self.reader.as_mut().unwrap(); 63 | let n = try_nb!(reader.read(&mut self.buf)); 64 | if n == 0 { 65 | self.read_done = true; 66 | } else { 67 | self.pos = 0; 68 | self.cap = n; 69 | } 70 | } 71 | 72 | // If our buffer has some data, let's write it out! 73 | while self.pos < self.cap { 74 | let writer = self.writer.as_mut().unwrap(); 75 | let i = try_nb!(writer.write(&self.buf[self.pos..self.cap])); 76 | if i == 0 { 77 | return Err(io::Error::new(io::ErrorKind::WriteZero, 78 | "write zero byte into writer")); 79 | } else { 80 | self.pos += i; 81 | self.amt += i as u64; 82 | } 83 | } 84 | 85 | // If we've written al the data and we've seen EOF, flush out the 86 | // data and finish the transfer. 87 | // done with the entire transfer. 88 | if self.pos == self.cap && self.read_done { 89 | try_nb!(self.writer.as_mut().unwrap().flush()); 90 | let reader = self.reader.take().unwrap(); 91 | let writer = self.writer.take().unwrap(); 92 | return Ok((self.amt, reader, writer).into()) 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /tests/async_read.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio_io; 2 | extern crate bytes; 3 | extern crate futures; 4 | 5 | use tokio_io::AsyncRead; 6 | use bytes::{BytesMut, BufMut}; 7 | use futures::Async; 8 | 9 | use std::io::{self, Read}; 10 | 11 | #[test] 12 | fn read_buf_success() { 13 | struct R; 14 | 15 | impl Read for R { 16 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 17 | buf[0..11].copy_from_slice(b"hello world"); 18 | Ok(11) 19 | } 20 | } 21 | 22 | impl AsyncRead for R {} 23 | 24 | let mut buf = BytesMut::with_capacity(65); 25 | 26 | let n = match R.read_buf(&mut buf).unwrap() { 27 | Async::Ready(n) => n, 28 | _ => panic!(), 29 | }; 30 | 31 | assert_eq!(11, n); 32 | assert_eq!(buf[..], b"hello world"[..]); 33 | } 34 | 35 | #[test] 36 | fn read_buf_error() { 37 | struct R; 38 | 39 | impl Read for R { 40 | fn read(&mut self, _: &mut [u8]) -> io::Result { 41 | Err(io::Error::new(io::ErrorKind::Other, "other")) 42 | } 43 | } 44 | 45 | impl AsyncRead for R {} 46 | 47 | let mut buf = BytesMut::with_capacity(65); 48 | 49 | let err = R.read_buf(&mut buf).unwrap_err(); 50 | assert_eq!(err.kind(), io::ErrorKind::Other); 51 | } 52 | 53 | #[test] 54 | fn read_buf_no_capacity() { 55 | struct R; 56 | 57 | impl Read for R { 58 | fn read(&mut self, _: &mut [u8]) -> io::Result { 59 | unimplemented!(); 60 | } 61 | } 62 | 63 | impl AsyncRead for R {} 64 | 65 | // Can't create BytesMut w/ zero capacity, so fill it up 66 | let mut buf = BytesMut::with_capacity(64); 67 | buf.put(&[0; 64][..]); 68 | 69 | let n = match R.read_buf(&mut buf).unwrap() { 70 | Async::Ready(n) => n, 71 | _ => panic!(), 72 | }; 73 | 74 | assert_eq!(0, n); 75 | } 76 | 77 | #[test] 78 | fn read_buf_no_uninitialized() { 79 | struct R; 80 | 81 | impl Read for R { 82 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 83 | for b in buf { 84 | assert_eq!(0, *b); 85 | } 86 | 87 | Ok(0) 88 | } 89 | } 90 | 91 | impl AsyncRead for R {} 92 | 93 | // Can't create BytesMut w/ zero capacity, so fill it up 94 | let mut buf = BytesMut::with_capacity(64); 95 | 96 | let n = match R.read_buf(&mut buf).unwrap() { 97 | Async::Ready(n) => n, 98 | _ => panic!(), 99 | }; 100 | 101 | assert_eq!(0, n); 102 | } 103 | 104 | #[test] 105 | fn read_buf_uninitialized_ok() { 106 | struct R; 107 | 108 | impl Read for R { 109 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 110 | assert_eq!(buf[0..11], b"hello world"[..]); 111 | Ok(0) 112 | } 113 | } 114 | 115 | impl AsyncRead for R { 116 | unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { 117 | false 118 | } 119 | } 120 | 121 | // Can't create BytesMut w/ zero capacity, so fill it up 122 | let mut buf = BytesMut::with_capacity(64); 123 | unsafe { 124 | buf.bytes_mut()[0..11].copy_from_slice(b"hello world"); 125 | } 126 | 127 | let n = match R.read_buf(&mut buf).unwrap() { 128 | Async::Ready(n) => n, 129 | _ => panic!(), 130 | }; 131 | 132 | assert_eq!(0, n); 133 | } 134 | 135 | #[test] 136 | fn read_buf_translate_wouldblock_to_not_ready() { 137 | struct R; 138 | 139 | impl Read for R { 140 | fn read(&mut self, _: &mut [u8]) -> io::Result { 141 | Err(io::Error::new(io::ErrorKind::WouldBlock, "")) 142 | } 143 | } 144 | 145 | impl AsyncRead for R {} 146 | 147 | let mut buf = BytesMut::with_capacity(65); 148 | assert!(!R.read_buf(&mut buf).unwrap().is_ready()); 149 | } 150 | -------------------------------------------------------------------------------- /tests/framed_write.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio_io; 2 | extern crate bytes; 3 | extern crate futures; 4 | 5 | use tokio_io::AsyncWrite; 6 | use tokio_io::codec::{Encoder, FramedWrite}; 7 | 8 | use futures::{Sink, Poll}; 9 | use bytes::{BytesMut, BufMut, BigEndian}; 10 | 11 | use std::io::{self, Write}; 12 | use std::collections::VecDeque; 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 | struct U32Encoder; 23 | 24 | impl Encoder for U32Encoder { 25 | type Item = u32; 26 | type Error = io::Error; 27 | 28 | fn encode(&mut self, item: u32, dst: &mut BytesMut) -> io::Result<()> { 29 | // Reserve space 30 | dst.reserve(4); 31 | dst.put_u32::(item); 32 | Ok(()) 33 | } 34 | } 35 | 36 | #[test] 37 | fn write_multi_frame_in_packet() { 38 | let mock = mock! { 39 | Ok(b"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()), 40 | }; 41 | 42 | let mut framed = FramedWrite::new(mock, U32Encoder); 43 | assert!(framed.start_send(0).unwrap().is_ready()); 44 | assert!(framed.start_send(1).unwrap().is_ready()); 45 | assert!(framed.start_send(2).unwrap().is_ready()); 46 | 47 | // Nothing written yet 48 | assert_eq!(1, framed.get_ref().calls.len()); 49 | 50 | // Flush the writes 51 | assert!(framed.poll_complete().unwrap().is_ready()); 52 | 53 | assert_eq!(0, framed.get_ref().calls.len()); 54 | } 55 | 56 | #[test] 57 | fn write_hits_backpressure() { 58 | const ITER: usize = 2 * 1024; 59 | 60 | let mut mock = mock! { 61 | // Block the `ITER`th write 62 | Err(io::Error::new(io::ErrorKind::WouldBlock, "not ready")), 63 | Ok(b"".to_vec()), 64 | }; 65 | 66 | for i in 0..(ITER + 1) { 67 | let mut b = BytesMut::with_capacity(4); 68 | b.put_u32::(i as u32); 69 | 70 | // Append to the end 71 | match mock.calls.back_mut().unwrap() { 72 | &mut Ok(ref mut data) => { 73 | // Write in 2kb chunks 74 | if data.len() < ITER { 75 | data.extend_from_slice(&b[..]); 76 | continue; 77 | } 78 | } 79 | _ => unreachable!(), 80 | } 81 | 82 | // Push a new new chunk 83 | mock.calls.push_back(Ok(b[..].to_vec())); 84 | } 85 | 86 | let mut framed = FramedWrite::new(mock, U32Encoder); 87 | 88 | for i in 0..ITER { 89 | assert!(framed.start_send(i as u32).unwrap().is_ready()); 90 | } 91 | 92 | // This should reject 93 | assert!(!framed.start_send(ITER as u32).unwrap().is_ready()); 94 | 95 | // This should succeed and start flushing the buffer. 96 | assert!(framed.start_send(ITER as u32).unwrap().is_ready()); 97 | 98 | // Flush the rest of the buffer 99 | assert!(framed.poll_complete().unwrap().is_ready()); 100 | 101 | // Ensure the mock is empty 102 | assert_eq!(0, framed.get_ref().calls.len()); 103 | } 104 | 105 | // ===== Mock ====== 106 | 107 | struct Mock { 108 | calls: VecDeque>>, 109 | } 110 | 111 | impl Write for Mock { 112 | fn write(&mut self, src: &[u8]) -> io::Result { 113 | match self.calls.pop_front() { 114 | Some(Ok(data)) => { 115 | assert!(src.len() >= data.len()); 116 | assert_eq!(&data[..], &src[..data.len()]); 117 | Ok(data.len()) 118 | } 119 | Some(Err(e)) => Err(e), 120 | None => panic!("unexpected write; {:?}", src), 121 | } 122 | } 123 | 124 | fn flush(&mut self) -> io::Result<()> { 125 | Ok(()) 126 | } 127 | } 128 | 129 | impl AsyncWrite for Mock { 130 | fn shutdown(&mut self) -> Poll<(), io::Error> { 131 | Ok(().into()) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/codecs.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Bytes, BufMut, BytesMut}; 2 | use codec::{Encoder, Decoder}; 3 | use std::{io, str}; 4 | 5 | /// A simple `Codec` implementation that just ships bytes around. 6 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 7 | pub struct BytesCodec(()); 8 | 9 | impl BytesCodec { 10 | /// Creates a new `BytesCodec` for shipping around raw bytes. 11 | pub fn new() -> BytesCodec { BytesCodec(()) } 12 | } 13 | 14 | impl Decoder for BytesCodec { 15 | type Item = BytesMut; 16 | type Error = io::Error; 17 | 18 | fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { 19 | if buf.len() > 0 { 20 | let len = buf.len(); 21 | Ok(Some(buf.split_to(len))) 22 | } else { 23 | Ok(None) 24 | } 25 | } 26 | } 27 | 28 | impl Encoder for BytesCodec { 29 | type Item = Bytes; 30 | type Error = io::Error; 31 | 32 | fn encode(&mut self, data: Bytes, buf: &mut BytesMut) -> Result<(), io::Error> { 33 | buf.reserve(data.len()); 34 | buf.put(data); 35 | Ok(()) 36 | } 37 | } 38 | 39 | /// A simple `Codec` implementation that splits up data into lines. 40 | #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 41 | pub struct LinesCodec { 42 | // Stored index of the next index to examine for a `\n` character. 43 | // This is used to optimize searching. 44 | // For example, if `decode` was called with `abc`, it would hold `3`, 45 | // because that is the next index to examine. 46 | // The next time `decode` is called with `abcde\n`, the method will 47 | // only look at `de\n` before returning. 48 | next_index: usize, 49 | } 50 | 51 | impl LinesCodec { 52 | /// Returns a `LinesCodec` for splitting up data into lines. 53 | pub fn new() -> LinesCodec { 54 | LinesCodec { next_index: 0 } 55 | } 56 | } 57 | 58 | fn utf8(buf: &[u8]) -> Result<&str, io::Error> { 59 | str::from_utf8(buf).map_err(|_| 60 | io::Error::new( 61 | io::ErrorKind::InvalidData, 62 | "Unable to decode input as UTF8")) 63 | } 64 | 65 | fn without_carriage_return(s: &[u8]) -> &[u8] { 66 | if let Some(&b'\r') = s.last() { 67 | &s[..s.len() - 1] 68 | } else { 69 | s 70 | } 71 | } 72 | 73 | impl Decoder for LinesCodec { 74 | type Item = String; 75 | type Error = io::Error; 76 | 77 | fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { 78 | if let Some(newline_offset) = 79 | buf[self.next_index..].iter().position(|b| *b == b'\n') 80 | { 81 | let newline_index = newline_offset + self.next_index; 82 | let line = buf.split_to(newline_index + 1); 83 | let line = &line[..line.len()-1]; 84 | let line = without_carriage_return(line); 85 | let line = utf8(line)?; 86 | self.next_index = 0; 87 | Ok(Some(line.to_string())) 88 | } else { 89 | self.next_index = buf.len(); 90 | Ok(None) 91 | } 92 | } 93 | 94 | fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, io::Error> { 95 | Ok(match self.decode(buf)? { 96 | Some(frame) => Some(frame), 97 | None => { 98 | // No terminating newline - return remaining data, if any 99 | if buf.is_empty() || buf == &b"\r"[..] { 100 | None 101 | } else { 102 | let line = buf.take(); 103 | let line = without_carriage_return(&line); 104 | let line = utf8(line)?; 105 | self.next_index = 0; 106 | Some(line.to_string()) 107 | } 108 | } 109 | }) 110 | } 111 | } 112 | 113 | impl Encoder for LinesCodec { 114 | type Item = String; 115 | type Error = io::Error; 116 | 117 | fn encode(&mut self, line: String, buf: &mut BytesMut) -> Result<(), io::Error> { 118 | buf.reserve(line.len() + 1); 119 | buf.put(line); 120 | buf.put_u8(b'\n'); 121 | Ok(()) 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/window.rs: -------------------------------------------------------------------------------- 1 | use std::ops; 2 | 3 | /// A owned window around an underlying buffer. 4 | /// 5 | /// Normally slices work great for considering sub-portions of a buffer, but 6 | /// unfortunately a slice is a *borrowed* type in Rust which has an associated 7 | /// lifetime. When working with future and async I/O these lifetimes are not 8 | /// always appropriate, and are sometimes difficult to store in tasks. This 9 | /// type strives to fill this gap by providing an "owned slice" around an 10 | /// underlying buffer of bytes. 11 | /// 12 | /// A `Window` wraps an underlying buffer, `T`, and has configurable 13 | /// start/end indexes to alter the behavior of the `AsRef<[u8]>` implementation 14 | /// that this type carries. 15 | /// 16 | /// This type can be particularly useful when working with the `write_all` 17 | /// combinator in this crate. Data can be sliced via `Window`, consumed by 18 | /// `write_all`, and then earned back once the write operation finishes through 19 | /// the `into_inner` method on this type. 20 | #[derive(Debug)] 21 | pub struct Window { 22 | inner: T, 23 | range: ops::Range, 24 | } 25 | 26 | impl> Window { 27 | /// Creates a new window around the buffer `t` defaulting to the entire 28 | /// slice. 29 | /// 30 | /// Further methods can be called on the returned `Window` to alter the 31 | /// window into the data provided. 32 | pub fn new(t: T) -> Window { 33 | Window { 34 | range: 0..t.as_ref().len(), 35 | inner: t, 36 | } 37 | } 38 | 39 | /// Gets a shared reference to the underlying buffer inside of this 40 | /// `Window`. 41 | pub fn get_ref(&self) -> &T { 42 | &self.inner 43 | } 44 | 45 | /// Gets a mutable reference to the underlying buffer inside of this 46 | /// `Window`. 47 | pub fn get_mut(&mut self) -> &mut T { 48 | &mut self.inner 49 | } 50 | 51 | /// Consumes this `Window`, returning the underlying buffer. 52 | pub fn into_inner(self) -> T { 53 | self.inner 54 | } 55 | 56 | /// Returns the starting index of this window into the underlying buffer 57 | /// `T`. 58 | pub fn start(&self) -> usize { 59 | self.range.start 60 | } 61 | 62 | /// Returns the end index of this window into the underlying buffer 63 | /// `T`. 64 | pub fn end(&self) -> usize { 65 | self.range.end 66 | } 67 | 68 | /// Changes the starting index of this window to the index specified. 69 | /// 70 | /// Returns the windows back to chain multiple calls to this method. 71 | /// 72 | /// # Panics 73 | /// 74 | /// This method will panic if `start` is out of bounds for the underlying 75 | /// slice or if it comes after the `end` configured in this window. 76 | pub fn set_start(&mut self, start: usize) -> &mut Window { 77 | assert!(start <= self.inner.as_ref().len()); 78 | assert!(start <= self.range.end); 79 | self.range.start = start; 80 | self 81 | } 82 | 83 | /// Changes the end index of this window to the index specified. 84 | /// 85 | /// Returns the windows back to chain multiple calls to this method. 86 | /// 87 | /// # Panics 88 | /// 89 | /// This method will panic if `end` is out of bounds for the underlying 90 | /// slice or if it comes before the `start` configured in this window. 91 | pub fn set_end(&mut self, end: usize) -> &mut Window { 92 | assert!(end <= self.inner.as_ref().len()); 93 | assert!(self.range.start <= end); 94 | self.range.end = end; 95 | self 96 | } 97 | 98 | // TODO: how about a generic set() method along the lines of: 99 | // 100 | // buffer.set(..3) 101 | // .set(0..2) 102 | // .set(4..) 103 | // 104 | // etc. 105 | } 106 | 107 | impl> AsRef<[u8]> for Window { 108 | fn as_ref(&self) -> &[u8] { 109 | &self.inner.as_ref()[self.range.start..self.range.end] 110 | } 111 | } 112 | 113 | impl> AsMut<[u8]> for Window { 114 | fn as_mut(&mut self) -> &mut [u8] { 115 | &mut self.inner.as_mut()[self.range.start..self.range.end] 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /tests/framed_read.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio_io; 2 | extern crate bytes; 3 | extern crate futures; 4 | 5 | use tokio_io::AsyncRead; 6 | use tokio_io::codec::{FramedRead, Decoder}; 7 | 8 | use bytes::{BytesMut, Buf, IntoBuf, BigEndian}; 9 | use futures::Stream; 10 | use futures::Async::{Ready, NotReady}; 11 | 12 | use std::io::{self, Read}; 13 | use std::collections::VecDeque; 14 | 15 | macro_rules! mock { 16 | ($($x:expr,)*) => {{ 17 | let mut v = VecDeque::new(); 18 | v.extend(vec![$($x),*]); 19 | Mock { calls: v } 20 | }}; 21 | } 22 | 23 | struct U32Decoder; 24 | 25 | impl Decoder for U32Decoder { 26 | type Item = u32; 27 | type Error = io::Error; 28 | 29 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 30 | if buf.len() < 4 { 31 | return Ok(None); 32 | } 33 | 34 | let n = buf.split_to(4).into_buf().get_u32::(); 35 | Ok(Some(n)) 36 | } 37 | } 38 | 39 | #[test] 40 | fn read_multi_frame_in_packet() { 41 | let mock = mock! { 42 | Ok(b"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()), 43 | }; 44 | 45 | let mut framed = FramedRead::new(mock, U32Decoder); 46 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 47 | assert_eq!(Ready(Some(1)), framed.poll().unwrap()); 48 | assert_eq!(Ready(Some(2)), framed.poll().unwrap()); 49 | assert_eq!(Ready(None), framed.poll().unwrap()); 50 | } 51 | 52 | #[test] 53 | fn read_multi_frame_across_packets() { 54 | let mock = mock! { 55 | Ok(b"\x00\x00\x00\x00".to_vec()), 56 | Ok(b"\x00\x00\x00\x01".to_vec()), 57 | Ok(b"\x00\x00\x00\x02".to_vec()), 58 | }; 59 | 60 | let mut framed = FramedRead::new(mock, U32Decoder); 61 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 62 | assert_eq!(Ready(Some(1)), framed.poll().unwrap()); 63 | assert_eq!(Ready(Some(2)), framed.poll().unwrap()); 64 | assert_eq!(Ready(None), framed.poll().unwrap()); 65 | } 66 | 67 | #[test] 68 | fn read_not_ready() { 69 | let mock = mock! { 70 | Err(io::Error::new(io::ErrorKind::WouldBlock, "")), 71 | Ok(b"\x00\x00\x00\x00".to_vec()), 72 | Ok(b"\x00\x00\x00\x01".to_vec()), 73 | }; 74 | 75 | let mut framed = FramedRead::new(mock, U32Decoder); 76 | assert_eq!(NotReady, framed.poll().unwrap()); 77 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 78 | assert_eq!(Ready(Some(1)), framed.poll().unwrap()); 79 | assert_eq!(Ready(None), framed.poll().unwrap()); 80 | } 81 | 82 | #[test] 83 | fn read_partial_then_not_ready() { 84 | let mock = mock! { 85 | Ok(b"\x00\x00".to_vec()), 86 | Err(io::Error::new(io::ErrorKind::WouldBlock, "")), 87 | Ok(b"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()), 88 | }; 89 | 90 | let mut framed = FramedRead::new(mock, U32Decoder); 91 | assert_eq!(NotReady, framed.poll().unwrap()); 92 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 93 | assert_eq!(Ready(Some(1)), framed.poll().unwrap()); 94 | assert_eq!(Ready(Some(2)), framed.poll().unwrap()); 95 | assert_eq!(Ready(None), framed.poll().unwrap()); 96 | } 97 | 98 | #[test] 99 | fn read_err() { 100 | let mock = mock! { 101 | Err(io::Error::new(io::ErrorKind::Other, "")), 102 | }; 103 | 104 | let mut framed = FramedRead::new(mock, U32Decoder); 105 | assert_eq!(io::ErrorKind::Other, framed.poll().unwrap_err().kind()); 106 | } 107 | 108 | #[test] 109 | fn read_partial_then_err() { 110 | let mock = mock! { 111 | Ok(b"\x00\x00".to_vec()), 112 | Err(io::Error::new(io::ErrorKind::Other, "")), 113 | }; 114 | 115 | let mut framed = FramedRead::new(mock, U32Decoder); 116 | assert_eq!(io::ErrorKind::Other, framed.poll().unwrap_err().kind()); 117 | } 118 | 119 | #[test] 120 | fn read_partial_would_block_then_err() { 121 | let mock = mock! { 122 | Ok(b"\x00\x00".to_vec()), 123 | Err(io::Error::new(io::ErrorKind::WouldBlock, "")), 124 | Err(io::Error::new(io::ErrorKind::Other, "")), 125 | }; 126 | 127 | let mut framed = FramedRead::new(mock, U32Decoder); 128 | assert_eq!(NotReady, framed.poll().unwrap()); 129 | assert_eq!(io::ErrorKind::Other, framed.poll().unwrap_err().kind()); 130 | } 131 | 132 | #[test] 133 | fn huge_size() { 134 | let data = [0; 32 * 1024]; 135 | 136 | let mut framed = FramedRead::new(&data[..], BigDecoder); 137 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 138 | assert_eq!(Ready(None), framed.poll().unwrap()); 139 | 140 | struct BigDecoder; 141 | 142 | impl Decoder for BigDecoder { 143 | type Item = u32; 144 | type Error = io::Error; 145 | 146 | fn decode(&mut self, buf: &mut BytesMut) -> io::Result> { 147 | if buf.len() < 32 * 1024 { 148 | return Ok(None); 149 | } 150 | buf.split_to(32 * 1024); 151 | Ok(Some(0)) 152 | } 153 | } 154 | } 155 | 156 | #[test] 157 | fn data_remaining_is_error() { 158 | let data = [0; 5]; 159 | 160 | let mut framed = FramedRead::new(&data[..], U32Decoder); 161 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 162 | assert!(framed.poll().is_err()); 163 | } 164 | 165 | #[test] 166 | fn multi_frames_on_eof() { 167 | struct MyDecoder(Vec); 168 | 169 | impl Decoder for MyDecoder { 170 | type Item = u32; 171 | type Error = io::Error; 172 | 173 | fn decode(&mut self, _buf: &mut BytesMut) -> io::Result> { 174 | unreachable!(); 175 | } 176 | 177 | fn decode_eof(&mut self, _buf: &mut BytesMut) -> io::Result> { 178 | if self.0.is_empty() { 179 | return Ok(None); 180 | } 181 | 182 | Ok(Some(self.0.remove(0))) 183 | } 184 | } 185 | 186 | let mut framed = FramedRead::new(mock!(), MyDecoder(vec![0, 1, 2, 3])); 187 | assert_eq!(Ready(Some(0)), framed.poll().unwrap()); 188 | assert_eq!(Ready(Some(1)), framed.poll().unwrap()); 189 | assert_eq!(Ready(Some(2)), framed.poll().unwrap()); 190 | assert_eq!(Ready(Some(3)), framed.poll().unwrap()); 191 | assert_eq!(Ready(None), framed.poll().unwrap()); 192 | } 193 | 194 | // ===== Mock ====== 195 | 196 | struct Mock { 197 | calls: VecDeque>>, 198 | } 199 | 200 | impl Read for Mock { 201 | fn read(&mut self, dst: &mut [u8]) -> io::Result { 202 | match self.calls.pop_front() { 203 | Some(Ok(data)) => { 204 | debug_assert!(dst.len() >= data.len()); 205 | dst[..data.len()].copy_from_slice(&data[..]); 206 | Ok(data.len()) 207 | } 208 | Some(Err(e)) => Err(e), 209 | None => Ok(0), 210 | } 211 | } 212 | } 213 | 214 | impl AsyncRead for Mock { 215 | } 216 | -------------------------------------------------------------------------------- /src/framed_write.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Read}; 2 | use std::fmt; 3 | 4 | use {AsyncRead, AsyncWrite}; 5 | use codec::Decoder; 6 | use framed::Fuse; 7 | 8 | use futures::{Async, AsyncSink, Poll, Stream, Sink, StartSend}; 9 | use bytes::BytesMut; 10 | 11 | /// Trait of helper objects to write out messages as bytes, for use with 12 | /// `FramedWrite`. 13 | pub trait Encoder { 14 | /// The type of items consumed by the `Encoder` 15 | type Item; 16 | 17 | /// The type of encoding errors. 18 | /// 19 | /// `FramedWrite` requires `Encoder`s errors to implement `From` 20 | /// in the interest letting it return `Error`s directly. 21 | type Error: From; 22 | 23 | /// Encodes a frame into the buffer provided. 24 | /// 25 | /// This method will encode `item` into the byte buffer provided by `dst`. 26 | /// The `dst` provided is an internal buffer of the `Framed` instance and 27 | /// will be written out when possible. 28 | fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) 29 | -> Result<(), Self::Error>; 30 | } 31 | 32 | /// A `Sink` of frames encoded to an `AsyncWrite`. 33 | pub struct FramedWrite { 34 | inner: FramedWrite2>, 35 | } 36 | 37 | pub struct FramedWrite2 { 38 | inner: T, 39 | buffer: BytesMut, 40 | } 41 | 42 | const INITIAL_CAPACITY: usize = 8 * 1024; 43 | const BACKPRESSURE_BOUNDARY: usize = INITIAL_CAPACITY; 44 | 45 | impl FramedWrite 46 | where T: AsyncWrite, 47 | E: Encoder, 48 | { 49 | /// Creates a new `FramedWrite` with the given `encoder`. 50 | pub fn new(inner: T, encoder: E) -> FramedWrite { 51 | FramedWrite { 52 | inner: framed_write2(Fuse(inner, encoder)), 53 | } 54 | } 55 | } 56 | 57 | impl FramedWrite { 58 | /// Returns a reference to the underlying I/O stream wrapped by 59 | /// `FramedWrite`. 60 | /// 61 | /// Note that care should be taken to not tamper with the underlying stream 62 | /// of data coming in as it may corrupt the stream of frames otherwise 63 | /// being worked with. 64 | pub fn get_ref(&self) -> &T { 65 | &self.inner.inner.0 66 | } 67 | 68 | /// Returns a mutable reference to the underlying I/O stream wrapped by 69 | /// `FramedWrite`. 70 | /// 71 | /// Note that care should be taken to not tamper with the underlying stream 72 | /// of data coming in as it may corrupt the stream of frames otherwise 73 | /// being worked with. 74 | pub fn get_mut(&mut self) -> &mut T { 75 | &mut self.inner.inner.0 76 | } 77 | 78 | /// Consumes the `FramedWrite`, returning its underlying I/O stream. 79 | /// 80 | /// Note that care should be taken to not tamper with the underlying stream 81 | /// of data coming in as it may corrupt the stream of frames otherwise 82 | /// being worked with. 83 | pub fn into_inner(self) -> T { 84 | self.inner.inner.0 85 | } 86 | 87 | /// Returns a reference to the underlying decoder. 88 | pub fn encoder(&self) -> &E { 89 | &self.inner.inner.1 90 | } 91 | 92 | /// Returns a mutable reference to the underlying decoder. 93 | pub fn encoder_mut(&mut self) -> &mut E { 94 | &mut self.inner.inner.1 95 | } 96 | } 97 | 98 | impl Sink for FramedWrite 99 | where T: AsyncWrite, 100 | E: Encoder, 101 | { 102 | type SinkItem = E::Item; 103 | type SinkError = E::Error; 104 | 105 | fn start_send(&mut self, item: E::Item) -> StartSend { 106 | self.inner.start_send(item) 107 | } 108 | 109 | fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { 110 | self.inner.poll_complete() 111 | } 112 | 113 | fn close(&mut self) -> Poll<(), Self::SinkError> { 114 | Ok(try!(self.inner.close())) 115 | } 116 | } 117 | 118 | impl Stream for FramedWrite 119 | where T: Stream, 120 | { 121 | type Item = T::Item; 122 | type Error = T::Error; 123 | 124 | fn poll(&mut self) -> Poll, Self::Error> { 125 | self.inner.inner.0.poll() 126 | } 127 | } 128 | 129 | impl fmt::Debug for FramedWrite 130 | where T: fmt::Debug, 131 | U: fmt::Debug, 132 | { 133 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 134 | f.debug_struct("FramedWrite") 135 | .field("inner", &self.inner.get_ref().0) 136 | .field("encoder", &self.inner.get_ref().1) 137 | .field("buffer", &self.inner.buffer) 138 | .finish() 139 | } 140 | } 141 | 142 | // ===== impl FramedWrite2 ===== 143 | 144 | pub fn framed_write2(inner: T) -> FramedWrite2 { 145 | FramedWrite2 { 146 | inner: inner, 147 | buffer: BytesMut::with_capacity(INITIAL_CAPACITY), 148 | } 149 | } 150 | 151 | pub fn framed_write2_with_buffer(inner: T, mut buf: BytesMut) -> FramedWrite2 { 152 | if buf.capacity() < INITIAL_CAPACITY { 153 | let bytes_to_reserve = INITIAL_CAPACITY - buf.capacity(); 154 | buf.reserve(bytes_to_reserve); 155 | } 156 | FramedWrite2 { 157 | inner: inner, 158 | buffer: buf, 159 | } 160 | } 161 | 162 | impl FramedWrite2 { 163 | pub fn get_ref(&self) -> &T { 164 | &self.inner 165 | } 166 | 167 | pub fn into_inner(self) -> T { 168 | self.inner 169 | } 170 | 171 | pub fn into_parts(self) -> (T, BytesMut) { 172 | (self.inner, self.buffer) 173 | } 174 | 175 | pub fn get_mut(&mut self) -> &mut T { 176 | &mut self.inner 177 | } 178 | } 179 | 180 | impl Sink for FramedWrite2 181 | where T: AsyncWrite + Encoder, 182 | { 183 | type SinkItem = T::Item; 184 | type SinkError = T::Error; 185 | 186 | fn start_send(&mut self, item: T::Item) -> StartSend { 187 | // If the buffer is already over 8KiB, then attempt to flush it. If after flushing it's 188 | // *still* over 8KiB, then apply backpressure (reject the send). 189 | if self.buffer.len() >= BACKPRESSURE_BOUNDARY { 190 | try!(self.poll_complete()); 191 | 192 | if self.buffer.len() >= BACKPRESSURE_BOUNDARY { 193 | return Ok(AsyncSink::NotReady(item)); 194 | } 195 | } 196 | 197 | try!(self.inner.encode(item, &mut self.buffer)); 198 | 199 | Ok(AsyncSink::Ready) 200 | } 201 | 202 | fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { 203 | trace!("flushing framed transport"); 204 | 205 | while !self.buffer.is_empty() { 206 | trace!("writing; remaining={}", self.buffer.len()); 207 | 208 | let n = try_nb!(self.inner.write(&self.buffer)); 209 | 210 | if n == 0 { 211 | return Err(io::Error::new(io::ErrorKind::WriteZero, "failed to 212 | write frame to transport").into()); 213 | } 214 | 215 | // TODO: Add a way to `bytes` to do this w/o returning the drained 216 | // data. 217 | let _ = self.buffer.split_to(n); 218 | } 219 | 220 | // Try flushing the underlying IO 221 | try_nb!(self.inner.flush()); 222 | 223 | trace!("framed transport flushed"); 224 | return Ok(Async::Ready(())); 225 | } 226 | 227 | fn close(&mut self) -> Poll<(), Self::SinkError> { 228 | try_ready!(self.poll_complete()); 229 | Ok(try!(self.inner.shutdown())) 230 | } 231 | } 232 | 233 | impl Decoder for FramedWrite2 { 234 | type Item = T::Item; 235 | type Error = T::Error; 236 | 237 | fn decode(&mut self, src: &mut BytesMut) -> Result, T::Error> { 238 | self.inner.decode(src) 239 | } 240 | 241 | fn decode_eof(&mut self, src: &mut BytesMut) -> Result, T::Error> { 242 | self.inner.decode_eof(src) 243 | } 244 | } 245 | 246 | impl Read for FramedWrite2 { 247 | fn read(&mut self, dst: &mut [u8]) -> io::Result { 248 | self.inner.read(dst) 249 | } 250 | } 251 | 252 | impl AsyncRead for FramedWrite2 { 253 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 254 | self.inner.prepare_uninitialized_buffer(buf) 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/framed.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Read, Write}; 2 | use std::fmt; 3 | 4 | use {AsyncRead, AsyncWrite}; 5 | use framed_read::{framed_read2, framed_read2_with_buffer, FramedRead2, Decoder}; 6 | use framed_write::{framed_write2, framed_write2_with_buffer, FramedWrite2, Encoder}; 7 | 8 | use futures::{Stream, Sink, StartSend, Poll}; 9 | use bytes::{BytesMut}; 10 | 11 | /// A unified `Stream` and `Sink` interface to an underlying I/O object, using 12 | /// the `Encoder` and `Decoder` traits to encode and decode frames. 13 | /// 14 | /// You can create a `Framed` instance by using the `AsyncRead::framed` adapter. 15 | pub struct Framed { 16 | inner: FramedRead2>>, 17 | } 18 | 19 | pub struct Fuse(pub T, pub U); 20 | 21 | pub fn framed(inner: T, codec: U) -> Framed 22 | where T: AsyncRead + AsyncWrite, 23 | U: Decoder + Encoder, 24 | { 25 | Framed { 26 | inner: framed_read2(framed_write2(Fuse(inner, codec))), 27 | } 28 | } 29 | 30 | impl Framed { 31 | /// Provides a `Stream` and `Sink` interface for reading and writing to this 32 | /// `Io` object, using `Decode` and `Encode` to read and write the raw data. 33 | /// 34 | /// Raw I/O objects work with byte sequences, but higher-level code usually 35 | /// wants to batch these into meaningful chunks, called "frames". This 36 | /// method layers framing on top of an I/O object, by using the `Codec` 37 | /// traits to handle encoding and decoding of messages frames. Note that 38 | /// the incoming and outgoing frame types may be distinct. 39 | /// 40 | /// This function returns a *single* object that is both `Stream` and 41 | /// `Sink`; grouping this into a single object is often useful for layering 42 | /// things like gzip or TLS, which require both read and write access to the 43 | /// underlying object. 44 | /// 45 | /// This objects takes a stream and a readbuffer and a writebuffer. These field 46 | /// can be obtained from an existing `Framed` with the `into_parts` method. 47 | /// 48 | /// If you want to work more directly with the streams and sink, consider 49 | /// calling `split` on the `Framed` returned by this method, which will 50 | /// break them into separate objects, allowing them to interact more easily. 51 | pub fn from_parts(parts: FramedParts, codec: U) -> Framed 52 | { 53 | Framed { 54 | inner: framed_read2_with_buffer(framed_write2_with_buffer(Fuse(parts.inner, codec), parts.writebuf), parts.readbuf), 55 | } 56 | } 57 | 58 | /// Returns a reference to the underlying I/O stream wrapped by 59 | /// `Frame`. 60 | /// 61 | /// Note that care should be taken to not tamper with the underlying stream 62 | /// of data coming in as it may corrupt the stream of frames otherwise 63 | /// being worked with. 64 | pub fn get_ref(&self) -> &T { 65 | &self.inner.get_ref().get_ref().0 66 | } 67 | 68 | /// Returns a mutable reference to the underlying I/O stream wrapped by 69 | /// `Frame`. 70 | /// 71 | /// Note that care should be taken to not tamper with the underlying stream 72 | /// of data coming in as it may corrupt the stream of frames otherwise 73 | /// being worked with. 74 | pub fn get_mut(&mut self) -> &mut T { 75 | &mut self.inner.get_mut().get_mut().0 76 | } 77 | 78 | /// Consumes the `Frame`, returning its underlying I/O stream. 79 | /// 80 | /// Note that care should be taken to not tamper with the underlying stream 81 | /// of data coming in as it may corrupt the stream of frames otherwise 82 | /// being worked with. 83 | pub fn into_inner(self) -> T { 84 | self.inner.into_inner().into_inner().0 85 | } 86 | 87 | /// Consumes the `Frame`, returning its underlying I/O stream and the buffer 88 | /// with unprocessed data. 89 | /// 90 | /// Note that care should be taken to not tamper with the underlying stream 91 | /// of data coming in as it may corrupt the stream of frames otherwise 92 | /// being worked with. 93 | pub fn into_parts(self) -> FramedParts { 94 | let (inner, readbuf) = self.inner.into_parts(); 95 | let (inner, writebuf) = inner.into_parts(); 96 | FramedParts { inner: inner.0, readbuf: readbuf, writebuf: writebuf } 97 | } 98 | 99 | /// Consumes the `Frame`, returning its underlying I/O stream and the buffer 100 | /// with unprocessed data, and also the current codec state. 101 | /// 102 | /// Note that care should be taken to not tamper with the underlying stream 103 | /// of data coming in as it may corrupt the stream of frames otherwise 104 | /// being worked with. 105 | /// 106 | /// Note that this function will be removed once the codec has been 107 | /// integrated into `FramedParts` in a new version (see 108 | /// [#53](https://github.com/tokio-rs/tokio-io/pull/53)). 109 | pub fn into_parts_and_codec(self) -> (FramedParts, U) { 110 | let (inner, readbuf) = self.inner.into_parts(); 111 | let (inner, writebuf) = inner.into_parts(); 112 | (FramedParts { inner: inner.0, readbuf: readbuf, writebuf: writebuf }, inner.1) 113 | } 114 | } 115 | 116 | impl Stream for Framed 117 | where T: AsyncRead, 118 | U: Decoder, 119 | { 120 | type Item = U::Item; 121 | type Error = U::Error; 122 | 123 | fn poll(&mut self) -> Poll, Self::Error> { 124 | self.inner.poll() 125 | } 126 | } 127 | 128 | impl Sink for Framed 129 | where T: AsyncWrite, 130 | U: Encoder, 131 | U::Error: From, 132 | { 133 | type SinkItem = U::Item; 134 | type SinkError = U::Error; 135 | 136 | fn start_send(&mut self, 137 | item: Self::SinkItem) 138 | -> StartSend 139 | { 140 | self.inner.get_mut().start_send(item) 141 | } 142 | 143 | fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { 144 | self.inner.get_mut().poll_complete() 145 | } 146 | 147 | fn close(&mut self) -> Poll<(), Self::SinkError> { 148 | self.inner.get_mut().close() 149 | } 150 | } 151 | 152 | impl fmt::Debug for Framed 153 | where T: fmt::Debug, 154 | U: fmt::Debug, 155 | { 156 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 157 | f.debug_struct("Framed") 158 | .field("io", &self.inner.get_ref().get_ref().0) 159 | .field("codec", &self.inner.get_ref().get_ref().1) 160 | .finish() 161 | } 162 | } 163 | 164 | // ===== impl Fuse ===== 165 | 166 | impl Read for Fuse { 167 | fn read(&mut self, dst: &mut [u8]) -> io::Result { 168 | self.0.read(dst) 169 | } 170 | } 171 | 172 | impl AsyncRead for Fuse { 173 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 174 | self.0.prepare_uninitialized_buffer(buf) 175 | } 176 | } 177 | 178 | impl Write for Fuse { 179 | fn write(&mut self, src: &[u8]) -> io::Result { 180 | self.0.write(src) 181 | } 182 | 183 | fn flush(&mut self) -> io::Result<()> { 184 | self.0.flush() 185 | } 186 | } 187 | 188 | impl AsyncWrite for Fuse { 189 | fn shutdown(&mut self) -> Poll<(), io::Error> { 190 | self.0.shutdown() 191 | } 192 | } 193 | 194 | impl Decoder for Fuse { 195 | type Item = U::Item; 196 | type Error = U::Error; 197 | 198 | fn decode(&mut self, buffer: &mut BytesMut) -> Result, Self::Error> { 199 | self.1.decode(buffer) 200 | } 201 | 202 | fn decode_eof(&mut self, buffer: &mut BytesMut) -> Result, Self::Error> { 203 | self.1.decode_eof(buffer) 204 | } 205 | } 206 | 207 | impl Encoder for Fuse { 208 | type Item = U::Item; 209 | type Error = U::Error; 210 | 211 | fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { 212 | self.1.encode(item, dst) 213 | } 214 | } 215 | 216 | /// `FramedParts` contains an export of the data of a Framed transport. 217 | /// It can be used to construct a new `Framed` with a different codec. 218 | /// It contains all current buffers and the inner transport. 219 | #[derive(Debug)] 220 | pub struct FramedParts 221 | { 222 | /// The inner transport used to read bytes to and write bytes to 223 | pub inner: T, 224 | /// The buffer with read but unprocessed data. 225 | pub readbuf: BytesMut, 226 | /// A buffer with unprocessed data which are not written yet. 227 | pub writebuf: BytesMut 228 | } -------------------------------------------------------------------------------- /src/framed_read.rs: -------------------------------------------------------------------------------- 1 | use std::{fmt, io}; 2 | 3 | use AsyncRead; 4 | use framed::Fuse; 5 | 6 | use futures::{Async, Poll, Stream, Sink, StartSend}; 7 | use bytes::BytesMut; 8 | 9 | /// Decoding of frames via buffers. 10 | /// 11 | /// This trait is used when constructing an instance of `Framed` or 12 | /// `FramedRead`. An implementation of `Decoder` takes a byte stream that has 13 | /// already been buffered in `src` and decodes the data into a stream of 14 | /// `Self::Item` frames. 15 | /// 16 | /// Implementations are able to track state on `self`, which enables 17 | /// implementing stateful streaming parsers. In many cases, though, this type 18 | /// will simply be a unit struct (e.g. `struct HttpDecoder`). 19 | pub trait Decoder { 20 | /// The type of decoded frames. 21 | type Item; 22 | 23 | /// The type of unrecoverable frame decoding errors. 24 | /// 25 | /// If an individual message is ill-formed but can be ignored without 26 | /// interfering with the processing of future messages, it may be more 27 | /// useful to report the failure as an `Item`. 28 | /// 29 | /// `From` is required in the interest of making `Error` suitable 30 | /// for returning directly from a `FramedRead`, and to enable the default 31 | /// implementation of `decode_eof` to yield an `io::Error` when the decoder 32 | /// fails to consume all available data. 33 | /// 34 | /// Note that implementors of this trait can simply indicate `type Error = 35 | /// io::Error` to use I/O errors as this type. 36 | type Error: From; 37 | 38 | /// Attempts to decode a frame from the provided buffer of bytes. 39 | /// 40 | /// This method is called by `FramedRead` whenever bytes are ready to be 41 | /// parsed. The provided buffer of bytes is what's been read so far, and 42 | /// this instance of `Decode` can determine whether an entire frame is in 43 | /// the buffer and is ready to be returned. 44 | /// 45 | /// If an entire frame is available, then this instance will remove those 46 | /// bytes from the buffer provided and return them as a decoded 47 | /// frame. Note that removing bytes from the provided buffer doesn't always 48 | /// necessarily copy the bytes, so this should be an efficient operation in 49 | /// most circumstances. 50 | /// 51 | /// If the bytes look valid, but a frame isn't fully available yet, then 52 | /// `Ok(None)` is returned. This indicates to the `Framed` instance that 53 | /// it needs to read some more bytes before calling this method again. 54 | /// 55 | /// Note that the bytes provided may be empty. If a previous call to 56 | /// `decode` consumed all the bytes in the buffer then `decode` will be 57 | /// called again until it returns `None`, indicating that more bytes need to 58 | /// be read. 59 | /// 60 | /// Finally, if the bytes in the buffer are malformed then an error is 61 | /// returned indicating why. This informs `Framed` that the stream is now 62 | /// corrupt and should be terminated. 63 | fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error>; 64 | 65 | /// A default method available to be called when there are no more bytes 66 | /// available to be read from the underlying I/O. 67 | /// 68 | /// This method defaults to calling `decode` and returns an error if 69 | /// `Ok(None)` is returned while there is unconsumed data in `buf`. 70 | /// Typically this doesn't need to be implemented unless the framing 71 | /// protocol differs near the end of the stream. 72 | /// 73 | /// Note that the `buf` argument may be empty. If a previous call to 74 | /// `decode_eof` consumed all the bytes in the buffer, `decode_eof` will be 75 | /// called again until it returns `None`, indicating that there are no more 76 | /// frames to yield. This behavior enables returning finalization frames 77 | /// that may not be based on inbound data. 78 | fn decode_eof(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { 79 | match try!(self.decode(buf)) { 80 | Some(frame) => Ok(Some(frame)), 81 | None => { 82 | if buf.is_empty() { 83 | Ok(None) 84 | } else { 85 | Err(io::Error::new(io::ErrorKind::Other, 86 | "bytes remaining on stream").into()) 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | /// A `Stream` of messages decoded from an `AsyncRead`. 94 | pub struct FramedRead { 95 | inner: FramedRead2>, 96 | } 97 | 98 | pub struct FramedRead2 { 99 | inner: T, 100 | eof: bool, 101 | is_readable: bool, 102 | buffer: BytesMut, 103 | } 104 | 105 | const INITIAL_CAPACITY: usize = 8 * 1024; 106 | 107 | // ===== impl FramedRead ===== 108 | 109 | impl FramedRead 110 | where T: AsyncRead, 111 | D: Decoder, 112 | { 113 | /// Creates a new `FramedRead` with the given `decoder`. 114 | pub fn new(inner: T, decoder: D) -> FramedRead { 115 | FramedRead { 116 | inner: framed_read2(Fuse(inner, decoder)), 117 | } 118 | } 119 | } 120 | 121 | impl FramedRead { 122 | /// Returns a reference to the underlying I/O stream wrapped by 123 | /// `FramedRead`. 124 | /// 125 | /// Note that care should be taken to not tamper with the underlying stream 126 | /// of data coming in as it may corrupt the stream of frames otherwise 127 | /// being worked with. 128 | pub fn get_ref(&self) -> &T { 129 | &self.inner.inner.0 130 | } 131 | 132 | /// Returns a mutable reference to the underlying I/O stream wrapped by 133 | /// `FramedRead`. 134 | /// 135 | /// Note that care should be taken to not tamper with the underlying stream 136 | /// of data coming in as it may corrupt the stream of frames otherwise 137 | /// being worked with. 138 | pub fn get_mut(&mut self) -> &mut T { 139 | &mut self.inner.inner.0 140 | } 141 | 142 | /// Consumes the `FramedRead`, returning its underlying I/O stream. 143 | /// 144 | /// Note that care should be taken to not tamper with the underlying stream 145 | /// of data coming in as it may corrupt the stream of frames otherwise 146 | /// being worked with. 147 | pub fn into_inner(self) -> T { 148 | self.inner.inner.0 149 | } 150 | 151 | /// Returns a reference to the underlying decoder. 152 | pub fn decoder(&self) -> &D { 153 | &self.inner.inner.1 154 | } 155 | 156 | /// Returns a mutable reference to the underlying decoder. 157 | pub fn decoder_mut(&mut self) -> &mut D { 158 | &mut self.inner.inner.1 159 | } 160 | } 161 | 162 | impl Stream for FramedRead 163 | where T: AsyncRead, 164 | D: Decoder, 165 | { 166 | type Item = D::Item; 167 | type Error = D::Error; 168 | 169 | fn poll(&mut self) -> Poll, Self::Error> { 170 | self.inner.poll() 171 | } 172 | } 173 | 174 | impl Sink for FramedRead 175 | where T: Sink, 176 | { 177 | type SinkItem = T::SinkItem; 178 | type SinkError = T::SinkError; 179 | 180 | fn start_send(&mut self, 181 | item: Self::SinkItem) 182 | -> StartSend 183 | { 184 | self.inner.inner.0.start_send(item) 185 | } 186 | 187 | fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { 188 | self.inner.inner.0.poll_complete() 189 | } 190 | 191 | fn close(&mut self) -> Poll<(), Self::SinkError> { 192 | self.inner.inner.0.close() 193 | } 194 | } 195 | 196 | impl fmt::Debug for FramedRead 197 | where T: fmt::Debug, 198 | D: fmt::Debug, 199 | { 200 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 201 | f.debug_struct("FramedRead") 202 | .field("inner", &self.inner.inner.0) 203 | .field("decoder", &self.inner.inner.1) 204 | .field("eof", &self.inner.eof) 205 | .field("is_readable", &self.inner.is_readable) 206 | .field("buffer", &self.inner.buffer) 207 | .finish() 208 | } 209 | } 210 | 211 | // ===== impl FramedRead2 ===== 212 | 213 | pub fn framed_read2(inner: T) -> FramedRead2 { 214 | FramedRead2 { 215 | inner: inner, 216 | eof: false, 217 | is_readable: false, 218 | buffer: BytesMut::with_capacity(INITIAL_CAPACITY), 219 | } 220 | } 221 | 222 | pub fn framed_read2_with_buffer(inner: T, mut buf: BytesMut) -> FramedRead2 { 223 | if buf.capacity() < INITIAL_CAPACITY { 224 | let bytes_to_reserve = INITIAL_CAPACITY - buf.capacity(); 225 | buf.reserve(bytes_to_reserve); 226 | } 227 | FramedRead2 { 228 | inner: inner, 229 | eof: false, 230 | is_readable: buf.len() > 0, 231 | buffer: buf, 232 | } 233 | } 234 | 235 | impl FramedRead2 { 236 | pub fn get_ref(&self) -> &T { 237 | &self.inner 238 | } 239 | 240 | pub fn into_inner(self) -> T { 241 | self.inner 242 | } 243 | 244 | pub fn into_parts(self) -> (T, BytesMut) { 245 | (self.inner, self.buffer) 246 | } 247 | 248 | pub fn get_mut(&mut self) -> &mut T { 249 | &mut self.inner 250 | } 251 | } 252 | 253 | impl Stream for FramedRead2 254 | where T: AsyncRead + Decoder, 255 | { 256 | type Item = T::Item; 257 | type Error = T::Error; 258 | 259 | fn poll(&mut self) -> Poll, Self::Error> { 260 | loop { 261 | // Repeatedly call `decode` or `decode_eof` as long as it is 262 | // "readable". Readable is defined as not having returned `None`. If 263 | // the upstream has returned EOF, and the decoder is no longer 264 | // readable, it can be assumed that the decoder will never become 265 | // readable again, at which point the stream is terminated. 266 | if self.is_readable { 267 | if self.eof { 268 | let frame = try!(self.inner.decode_eof(&mut self.buffer)); 269 | return Ok(Async::Ready(frame)); 270 | } 271 | 272 | trace!("attempting to decode a frame"); 273 | 274 | if let Some(frame) = try!(self.inner.decode(&mut self.buffer)) { 275 | trace!("frame decoded from buffer"); 276 | return Ok(Async::Ready(Some(frame))); 277 | } 278 | 279 | self.is_readable = false; 280 | } 281 | 282 | assert!(!self.eof); 283 | 284 | // Otherwise, try to read more data and try again. Make sure we've 285 | // got room for at least one byte to read to ensure that we don't 286 | // get a spurious 0 that looks like EOF 287 | self.buffer.reserve(1); 288 | if 0 == try_ready!(self.inner.read_buf(&mut self.buffer)) { 289 | self.eof = true; 290 | } 291 | 292 | self.is_readable = true; 293 | } 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/codec.rs: -------------------------------------------------------------------------------- 1 | //! Utilities for encoding and decoding frames. 2 | //! 3 | //! Contains adapters to go from streams of bytes, [`AsyncRead`] and 4 | //! [`AsyncWrite`], to framed streams implementing [`Sink`] and [`Stream`]. 5 | //! Framed streams are also known as [transports]. 6 | //! 7 | //! [`AsyncRead`]: # 8 | //! [`AsyncWrite`]: # 9 | //! [`Sink`]: # 10 | //! [`Stream`]: # 11 | //! [transports]: # 12 | 13 | pub use codecs::{BytesCodec, LinesCodec}; 14 | pub use framed::{Framed, FramedParts}; 15 | pub use framed_read::{FramedRead, Decoder}; 16 | pub use framed_write::{FramedWrite, Encoder}; 17 | 18 | pub mod length_delimited { 19 | //! Frame a stream of bytes based on a length prefix 20 | //! 21 | //! Many protocols delimit their frames by prefacing frame data with a 22 | //! frame head that specifies the length of the frame. The 23 | //! `length_delimited` module provides utilities for handling the length 24 | //! based framing. This allows the consumer to work with entire frames 25 | //! without having to worry about buffering or other framing logic. 26 | //! 27 | //! # Getting started 28 | //! 29 | //! If implementing a protocol from scratch, using length delimited framing 30 | //! is an easy way to get started. [`Framed::new()`] will adapt a 31 | //! full-duplex byte stream with a length delimited framer using default 32 | //! configuration values. 33 | //! 34 | //! ``` 35 | //! use tokio_io::{AsyncRead, AsyncWrite}; 36 | //! use tokio_io::codec::length_delimited; 37 | //! 38 | //! fn bind_transport(io: T) 39 | //! -> length_delimited::Framed 40 | //! { 41 | //! length_delimited::Framed::new(io) 42 | //! } 43 | //! ``` 44 | //! 45 | //! The returned transport implements `Sink + Stream` for `BytesMut`. It 46 | //! encodes the frame with a big-endian `u32` header denoting the frame 47 | //! payload length: 48 | //! 49 | //! ```text 50 | //! +----------+--------------------------------+ 51 | //! | len: u32 | frame payload | 52 | //! +----------+--------------------------------+ 53 | //! ``` 54 | //! 55 | //! Specifically, given the following: 56 | //! 57 | //! ``` 58 | //! # extern crate tokio_io; 59 | //! # extern crate bytes; 60 | //! # extern crate futures; 61 | //! # 62 | //! use tokio_io::{AsyncRead, AsyncWrite}; 63 | //! use tokio_io::codec::length_delimited; 64 | //! use bytes::BytesMut; 65 | //! use futures::{Sink, Future}; 66 | //! 67 | //! fn write_frame(io: T) { 68 | //! let mut transport = length_delimited::Framed::new(io); 69 | //! let frame = BytesMut::from("hello world"); 70 | //! 71 | //! transport.send(frame).wait().unwrap(); 72 | //! } 73 | //! # 74 | //! # pub fn main() {} 75 | //! ``` 76 | //! 77 | //! The encoded frame will look like this: 78 | //! 79 | //! ```text 80 | //! +---- len: u32 ----+---- data ----+ 81 | //! | \x00\x00\x00\x0b | hello world | 82 | //! +------------------+--------------+ 83 | //! ``` 84 | //! 85 | //! # Decoding 86 | //! 87 | //! [`FramedRead`] adapts an [`AsyncRead`] into a `Stream` of [`BytesMut`], 88 | //! such that each yielded [`BytesMut`] value contains the contents of an 89 | //! entire frame. There are many configuration parameters enabling 90 | //! [`FrameRead`] to handle a wide range of protocols. Here are some 91 | //! examples that will cover the various options at a high level. 92 | //! 93 | //! ## Example 1 94 | //! 95 | //! The following will parse a `u16` length field at offset 0, including the 96 | //! frame head in the yielded `BytesMut`. 97 | //! 98 | //! ``` 99 | //! # use tokio_io::AsyncRead; 100 | //! # use tokio_io::codec::length_delimited; 101 | //! # fn bind_read(io: T) { 102 | //! length_delimited::Builder::new() 103 | //! .length_field_offset(0) // default value 104 | //! .length_field_length(2) 105 | //! .length_adjustment(0) // default value 106 | //! .num_skip(0) // Do not strip frame header 107 | //! .new_read(io); 108 | //! # } 109 | //! ``` 110 | //! 111 | //! The following frame will be decoded as such: 112 | //! 113 | //! ```text 114 | //! INPUT DECODED 115 | //! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+ 116 | //! | \x00\x0B | Hello world | --> | \x00\x0B | Hello world | 117 | //! +----------+---------------+ +----------+---------------+ 118 | //! ``` 119 | //! 120 | //! The value of the length field is 11 (`\x0B`) which represents the length 121 | //! of the payload, `hello world`. By default, [`FramedRead`] assumes that 122 | //! the length field represents the number of bytes that **follows** the 123 | //! length field. Thus, the entire frame has a length of 13: 2 bytes for the 124 | //! frame head + 11 bytes for the payload. 125 | //! 126 | //! ## Example 2 127 | //! 128 | //! The following will parse a `u16` length field at offset 0, omitting the 129 | //! frame head in the yielded `BytesMut`. 130 | //! 131 | //! ``` 132 | //! # use tokio_io::AsyncRead; 133 | //! # use tokio_io::codec::length_delimited; 134 | //! # fn bind_read(io: T) { 135 | //! length_delimited::Builder::new() 136 | //! .length_field_offset(0) // default value 137 | //! .length_field_length(2) 138 | //! .length_adjustment(0) // default value 139 | //! // `num_skip` is not needed, the default is to skip 140 | //! .new_read(io); 141 | //! # } 142 | //! ``` 143 | //! 144 | //! The following frame will be decoded as such: 145 | //! 146 | //! ```text 147 | //! INPUT DECODED 148 | //! +-- len ---+--- Payload ---+ +--- Payload ---+ 149 | //! | \x00\x0B | Hello world | --> | Hello world | 150 | //! +----------+---------------+ +---------------+ 151 | //! ``` 152 | //! 153 | //! This is similar to the first example, the only difference is that the 154 | //! frame head is **not** included in the yielded `BytesMut` value. 155 | //! 156 | //! ## Example 3 157 | //! 158 | //! The following will parse a `u16` length field at offset 0, including the 159 | //! frame head in the yielded `BytesMut`. In this case, the length field 160 | //! **includes** the frame head length. 161 | //! 162 | //! ``` 163 | //! # use tokio_io::AsyncRead; 164 | //! # use tokio_io::codec::length_delimited; 165 | //! # fn bind_read(io: T) { 166 | //! length_delimited::Builder::new() 167 | //! .length_field_offset(0) // default value 168 | //! .length_field_length(2) 169 | //! .length_adjustment(-2) // size of head 170 | //! .num_skip(0) 171 | //! .new_read(io); 172 | //! # } 173 | //! ``` 174 | //! 175 | //! The following frame will be decoded as such: 176 | //! 177 | //! ```text 178 | //! INPUT DECODED 179 | //! +-- len ---+--- Payload ---+ +-- len ---+--- Payload ---+ 180 | //! | \x00\x0D | Hello world | --> | \x00\x0D | Hello world | 181 | //! +----------+---------------+ +----------+---------------+ 182 | //! ``` 183 | //! 184 | //! In most cases, the length field represents the length of the payload 185 | //! only, as shown in the previous examples. However, in some protocols the 186 | //! length field represents the length of the whole frame, including the 187 | //! head. In such cases, we specify a negative `length_adjustment` to adjust 188 | //! the value provided in the frame head to represent the payload length. 189 | //! 190 | //! ## Example 4 191 | //! 192 | //! The following will parse a 3 byte length field at offset 0 in a 5 byte 193 | //! frame head, including the frame head in the yielded `BytesMut`. 194 | //! 195 | //! ``` 196 | //! # use tokio_io::AsyncRead; 197 | //! # use tokio_io::codec::length_delimited; 198 | //! # fn bind_read(io: T) { 199 | //! length_delimited::Builder::new() 200 | //! .length_field_offset(0) // default value 201 | //! .length_field_length(3) 202 | //! .length_adjustment(2) // remaining head 203 | //! .num_skip(0) 204 | //! .new_read(io); 205 | //! # } 206 | //! ``` 207 | //! 208 | //! The following frame will be decoded as such: 209 | //! 210 | //! ```text 211 | //! INPUT 212 | //! +---- len -----+- head -+--- Payload ---+ 213 | //! | \x00\x00\x0B | \xCAFE | Hello world | 214 | //! +--------------+--------+---------------+ 215 | //! 216 | //! DECODED 217 | //! +---- len -----+- head -+--- Payload ---+ 218 | //! | \x00\x00\x0B | \xCAFE | Hello world | 219 | //! +--------------+--------+---------------+ 220 | //! ``` 221 | //! 222 | //! A more advanced example that shows a case where there is extra frame 223 | //! head data between the length field and the payload. In such cases, it is 224 | //! usually desirable to include the frame head as part of the yielded 225 | //! `BytesMut`. This lets consumers of the length delimited framer to 226 | //! process the frame head as needed. 227 | //! 228 | //! The positive `length_adjustment` value lets `FramedRead` factor in the 229 | //! additional head into the frame length calculation. 230 | //! 231 | //! ## Example 5 232 | //! 233 | //! The following will parse a `u16` length field at offset 1 of a 4 byte 234 | //! frame head. The first byte and the length field will be omitted from the 235 | //! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be 236 | //! included. 237 | //! 238 | //! ``` 239 | //! # use tokio_io::AsyncRead; 240 | //! # use tokio_io::codec::length_delimited; 241 | //! # fn bind_read(io: T) { 242 | //! length_delimited::Builder::new() 243 | //! .length_field_offset(1) // length of hdr1 244 | //! .length_field_length(2) 245 | //! .length_adjustment(1) // length of hdr2 246 | //! .num_skip(3) // length of hdr1 + LEN 247 | //! .new_read(io); 248 | //! # } 249 | //! ``` 250 | //! 251 | //! The following frame will be decoded as such: 252 | //! 253 | //! ```text 254 | //! INPUT 255 | //! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+ 256 | //! | \xCA | \x00\x0B | \xFE | Hello world | 257 | //! +--------+----------+--------+---------------+ 258 | //! 259 | //! DECODED 260 | //! +- hdr2 -+--- Payload ---+ 261 | //! | \xFE | Hello world | 262 | //! +--------+---------------+ 263 | //! ``` 264 | //! 265 | //! The length field is situated in the middle of the frame head. In this 266 | //! case, the first byte in the frame head could be a version or some other 267 | //! identifier that is not needed for processing. On the other hand, the 268 | //! second half of the head is needed. 269 | //! 270 | //! `length_field_offset` indicates how many bytes to skip before starting 271 | //! to read the length field. `length_adjustment` is the number of bytes to 272 | //! skip starting at the end of the length field. In this case, it is the 273 | //! second half of the head. 274 | //! 275 | //! ## Example 6 276 | //! 277 | //! The following will parse a `u16` length field at offset 1 of a 4 byte 278 | //! frame head. The first byte and the length field will be omitted from the 279 | //! yielded `BytesMut`, but the trailing 2 bytes of the frame head will be 280 | //! included. In this case, the length field **includes** the frame head 281 | //! length. 282 | //! 283 | //! ``` 284 | //! # use tokio_io::AsyncRead; 285 | //! # use tokio_io::codec::length_delimited; 286 | //! # fn bind_read(io: T) { 287 | //! length_delimited::Builder::new() 288 | //! .length_field_offset(1) // length of hdr1 289 | //! .length_field_length(2) 290 | //! .length_adjustment(-3) // length of hdr1 + LEN, negative 291 | //! .num_skip(3) 292 | //! .new_read(io); 293 | //! # } 294 | //! ``` 295 | //! 296 | //! The following frame will be decoded as such: 297 | //! 298 | //! ```text 299 | //! INPUT 300 | //! +- hdr1 -+-- len ---+- hdr2 -+--- Payload ---+ 301 | //! | \xCA | \x00\x0F | \xFE | Hello world | 302 | //! +--------+----------+--------+---------------+ 303 | //! 304 | //! DECODED 305 | //! +- hdr2 -+--- Payload ---+ 306 | //! | \xFE | Hello world | 307 | //! +--------+---------------+ 308 | //! ``` 309 | //! 310 | //! Similar to the example above, the difference is that the length field 311 | //! represents the length of the entire frame instead of just the payload. 312 | //! The length of `hdr1` and `len` must be counted in `length_adjustment`. 313 | //! Note that the length of `hdr2` does **not** need to be explicitly set 314 | //! anywhere because it already is factored into the total frame length that 315 | //! is read from the byte stream. 316 | //! 317 | //! # Encoding 318 | //! 319 | //! [`FramedWrite`] adapts an [`AsyncWrite`] into a `Sink` of [`BytesMut`], 320 | //! such that each submitted [`BytesMut`] is prefaced by a length field. 321 | //! There are fewer configuration options than [`FramedRead`]. Given 322 | //! protocols that have more complex frame heads, an encoder should probably 323 | //! be written by hand using [`Encoder`]. 324 | //! 325 | //! Here is a simple example, given a `FramedWrite` with the following 326 | //! configuration: 327 | //! 328 | //! ``` 329 | //! # extern crate tokio_io; 330 | //! # extern crate bytes; 331 | //! # use tokio_io::AsyncWrite; 332 | //! # use tokio_io::codec::length_delimited; 333 | //! # use bytes::BytesMut; 334 | //! # fn write_frame(io: T) { 335 | //! # let _: length_delimited::FramedWrite = 336 | //! length_delimited::Builder::new() 337 | //! .length_field_length(2) 338 | //! .new_write(io); 339 | //! # } 340 | //! # pub fn main() {} 341 | //! ``` 342 | //! 343 | //! A payload of `hello world` will be encoded as: 344 | //! 345 | //! ```text 346 | //! +- len: u16 -+---- data ----+ 347 | //! | \x00\x0b | hello world | 348 | //! +------------+--------------+ 349 | //! ``` 350 | //! 351 | //! [`FramedRead`]: struct.FramedRead.html 352 | //! [`FramedWrite`]: struct.FramedWrite.html 353 | //! [`AsyncRead`]: ../../trait.AsyncRead.html 354 | //! [`AsyncWrite`]: ../../trait.AsyncWrite.html 355 | //! [`Encoder`]: ../trait.Encoder.html 356 | //! [`BytesMut`]: https://docs.rs/bytes/~0.4/bytes/struct.BytesMut.html 357 | 358 | pub use ::length_delimited::*; 359 | } 360 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Core I/O traits and combinators when working with Tokio. 2 | //! 3 | //! A description of the high-level I/O combinators can be [found online] in 4 | //! addition to a description of the [low level details]. 5 | //! 6 | //! [found online]: https://tokio.rs/docs/getting-started/core/ 7 | //! [low level details]: https://tokio.rs/docs/going-deeper-tokio/core-low-level/ 8 | 9 | #![deny(missing_docs, missing_debug_implementations, warnings)] 10 | #![doc(html_root_url = "https://docs.rs/tokio-io/0.1")] 11 | 12 | #[macro_use] 13 | extern crate log; 14 | 15 | #[macro_use] 16 | extern crate futures; 17 | extern crate bytes; 18 | 19 | use std::io as std_io; 20 | use std::io::Write; 21 | 22 | use futures::{Async, Future, Poll, Stream}; 23 | use bytes::{Buf, BufMut}; 24 | 25 | /// A convenience typedef around a `Future` whose error component is `io::Error` 26 | pub type IoFuture = Box + Send>; 27 | 28 | /// A convenience typedef around a `Stream` whose error component is `io::Error` 29 | pub type IoStream = Box + Send>; 30 | 31 | /// A convenience macro for working with `io::Result` from the `Read` and 32 | /// `Write` traits. 33 | /// 34 | /// This macro takes `io::Result` as input, and returns `T` as the output. If 35 | /// the input type is of the `Err` variant, then `Poll::NotReady` is returned if 36 | /// it indicates `WouldBlock` or otherwise `Err` is returned. 37 | #[macro_export] 38 | macro_rules! try_nb { 39 | ($e:expr) => (match $e { 40 | Ok(t) => t, 41 | Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => { 42 | return Ok(::futures::Async::NotReady) 43 | } 44 | Err(e) => return Err(e.into()), 45 | }) 46 | } 47 | 48 | pub mod io; 49 | pub mod codec; 50 | 51 | mod allow_std; 52 | mod codecs; 53 | mod copy; 54 | mod flush; 55 | mod framed; 56 | mod framed_read; 57 | mod framed_write; 58 | mod length_delimited; 59 | mod lines; 60 | mod read; 61 | mod read_exact; 62 | mod read_to_end; 63 | mod read_until; 64 | mod shutdown; 65 | mod split; 66 | mod window; 67 | mod write_all; 68 | 69 | use codec::{Decoder, Encoder, Framed}; 70 | use split::{ReadHalf, WriteHalf}; 71 | 72 | /// A trait for readable objects which operated in an asynchronous and 73 | /// futures-aware fashion. 74 | /// 75 | /// This trait inherits from `io::Read` and indicates as a marker that an I/O 76 | /// object is **nonblocking**, meaning that it will return an error instead of 77 | /// blocking when bytes are unavailable, but the stream hasn't reached EOF. 78 | /// Specifically this means that the `read` function for types that implement 79 | /// this trait can have a few return values: 80 | /// 81 | /// * `Ok(n)` means that `n` bytes of data was immediately read and placed into 82 | /// the output buffer, where `n` == 0 implies that EOF has been reached. 83 | /// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was read 84 | /// into the buffer provided. The I/O object is not currently readable but may 85 | /// become readable in the future. Most importantly, **the current future's 86 | /// task is scheduled to get unparked when the object is readable**. This 87 | /// means that like `Future::poll` you'll receive a notification when the I/O 88 | /// object is readable again. 89 | /// * `Err(e)` for other errors are standard I/O errors coming from the 90 | /// underlying object. 91 | /// 92 | /// This trait importantly means that the `read` method only works in the 93 | /// context of a future's task. The object may panic if used outside of a task. 94 | pub trait AsyncRead: std_io::Read { 95 | /// Prepares an uninitialized buffer to be safe to pass to `read`. Returns 96 | /// `true` if the supplied buffer was zeroed out. 97 | /// 98 | /// While it would be highly unusual, implementations of [`io::Read`] are 99 | /// able to read data from the buffer passed as an argument. Because of 100 | /// this, the buffer passed to [`io::Read`] must be initialized memory. In 101 | /// situations where large numbers of buffers are used, constantly having to 102 | /// zero out buffers can be expensive. 103 | /// 104 | /// This function does any necessary work to prepare an uninitialized buffer 105 | /// to be safe to pass to `read`. If `read` guarantees to never attempt read 106 | /// data out of the supplied buffer, then `prepare_uninitialized_buffer` 107 | /// doesn't need to do any work. 108 | /// 109 | /// If this function returns `true`, then the memory has been zeroed out. 110 | /// This allows implementations of `AsyncRead` which are composed of 111 | /// multiple sub implementations to efficiently implement 112 | /// `prepare_uninitialized_buffer`. 113 | /// 114 | /// This function isn't actually `unsafe` to call but `unsafe` to implement. 115 | /// The implementor must ensure that either the whole `buf` has been zeroed 116 | /// or `read_buf()` overwrites the buffer without reading it and returns 117 | /// correct value. 118 | /// 119 | /// This function is called from [`read_buf`]. 120 | /// 121 | /// [`io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html 122 | /// [`read_buf`]: #method.read_buf 123 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 124 | for i in 0..buf.len() { 125 | buf[i] = 0; 126 | } 127 | 128 | true 129 | } 130 | 131 | /// Pull some bytes from this source into the specified `Buf`, returning 132 | /// how many bytes were read. 133 | /// 134 | /// The `buf` provided will have bytes read into it and the internal cursor 135 | /// will be advanced if any bytes were read. Note that this method typically 136 | /// will not reallocate the buffer provided. 137 | fn read_buf(&mut self, buf: &mut B) -> Poll 138 | where Self: Sized, 139 | { 140 | if !buf.has_remaining_mut() { 141 | return Ok(Async::Ready(0)); 142 | } 143 | 144 | unsafe { 145 | let n = { 146 | let b = buf.bytes_mut(); 147 | 148 | self.prepare_uninitialized_buffer(b); 149 | 150 | try_nb!(self.read(b)) 151 | }; 152 | 153 | buf.advance_mut(n); 154 | Ok(Async::Ready(n)) 155 | } 156 | } 157 | 158 | /// Provides a `Stream` and `Sink` interface for reading and writing to this 159 | /// `Io` object, using `Decode` and `Encode` to read and write the raw data. 160 | /// 161 | /// Raw I/O objects work with byte sequences, but higher-level code usually 162 | /// wants to batch these into meaningful chunks, called "frames". This 163 | /// method layers framing on top of an I/O object, by using the `Codec` 164 | /// traits to handle encoding and decoding of messages frames. Note that 165 | /// the incoming and outgoing frame types may be distinct. 166 | /// 167 | /// This function returns a *single* object that is both `Stream` and 168 | /// `Sink`; grouping this into a single object is often useful for layering 169 | /// things like gzip or TLS, which require both read and write access to the 170 | /// underlying object. 171 | /// 172 | /// If you want to work more directly with the streams and sink, consider 173 | /// calling `split` on the `Framed` returned by this method, which will 174 | /// break them into separate objects, allowing them to interact more easily. 175 | fn framed(self, codec: T) -> Framed 176 | where Self: AsyncWrite + Sized, 177 | { 178 | framed::framed(self, codec) 179 | } 180 | 181 | /// Helper method for splitting this read/write object into two halves. 182 | /// 183 | /// The two halves returned implement the `Read` and `Write` traits, 184 | /// respectively. 185 | fn split(self) -> (ReadHalf, WriteHalf) 186 | where Self: AsyncWrite + Sized, 187 | { 188 | split::split(self) 189 | } 190 | } 191 | 192 | impl AsyncRead for Box { 193 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 194 | (**self).prepare_uninitialized_buffer(buf) 195 | } 196 | } 197 | 198 | impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T { 199 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 200 | (**self).prepare_uninitialized_buffer(buf) 201 | } 202 | } 203 | 204 | impl<'a> AsyncRead for &'a [u8] { 205 | unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool { 206 | false 207 | } 208 | } 209 | 210 | /// A trait for writable objects which operated in an asynchronous and 211 | /// futures-aware fashion. 212 | /// 213 | /// This trait inherits from `io::Write` and indicates that an I/O object is 214 | /// **nonblocking**, meaning that it will return an error instead of blocking 215 | /// when bytes cannot currently be written, but hasn't closed. Specifically 216 | /// this means that the `write` function for types that implement this trait 217 | /// can have a few return values: 218 | /// 219 | /// * `Ok(n)` means that `n` bytes of data was immediately written . 220 | /// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was 221 | /// written from the buffer provided. The I/O object is not currently 222 | /// writable but may become writable in the future. Most importantly, **the 223 | /// current future's task is scheduled to get unparked when the object is 224 | /// readable**. This means that like `Future::poll` you'll receive a 225 | /// notification when the I/O object is writable again. 226 | /// * `Err(e)` for other errors are standard I/O errors coming from the 227 | /// underlying object. 228 | /// 229 | /// This trait importantly means that the `write` method only works in the 230 | /// context of a future's task. The object may panic if used outside of a task. 231 | /// 232 | /// Note that this trait also represents that the `Write::flush` method works 233 | /// very similarly to the `write` method, notably that `Ok(())` means that the 234 | /// writer has successfully been flushed, a "would block" error means that the 235 | /// current task is ready to receive a notification when flushing can make more 236 | /// progress, and otherwise normal errors can happen as well. 237 | pub trait AsyncWrite: std_io::Write { 238 | /// Initiates or attempts to shut down this writer, returning success when 239 | /// the I/O connection has completely shut down. 240 | /// 241 | /// This method is intended to be used for asynchronous shutdown of I/O 242 | /// connections. For example this is suitable for implementing shutdown of a 243 | /// TLS connection or calling `TcpStream::shutdown` on a proxied connection. 244 | /// Protocols sometimes need to flush out final pieces of data or otherwise 245 | /// perform a graceful shutdown handshake, reading/writing more data as 246 | /// appropriate. This method is the hook for such protocols to implement the 247 | /// graceful shutdown logic. 248 | /// 249 | /// This `shutdown` method is required by implementors of the 250 | /// `AsyncWrite` trait. Wrappers typically just want to proxy this call 251 | /// through to the wrapped type, and base types will typically implement 252 | /// shutdown logic here or just return `Ok(().into())`. Note that if you're 253 | /// wrapping an underlying `AsyncWrite` a call to `shutdown` implies that 254 | /// transitively the entire stream has been shut down. After your wrapper's 255 | /// shutdown logic has been executed you should shut down the underlying 256 | /// stream. 257 | /// 258 | /// Invocation of a `shutdown` implies an invocation of `flush`. Once this 259 | /// method returns `Ready` it implies that a flush successfully happened 260 | /// before the shutdown happened. That is, callers don't need to call 261 | /// `flush` before calling `shutdown`. They can rely that by calling 262 | /// `shutdown` any pending buffered data will be written out. 263 | /// 264 | /// # Return value 265 | /// 266 | /// This function returns a `Poll<(), io::Error>` classified as such: 267 | /// 268 | /// * `Ok(Async::Ready(()))` - indicates that the connection was 269 | /// successfully shut down and is now safe to deallocate/drop/close 270 | /// resources associated with it. This method means that the current task 271 | /// will no longer receive any notifications due to this method and the 272 | /// I/O object itself is likely no longer usable. 273 | /// 274 | /// * `Ok(Async::NotReady)` - indicates that shutdown is initiated but could 275 | /// not complete just yet. This may mean that more I/O needs to happen to 276 | /// continue this shutdown operation. The current task is scheduled to 277 | /// receive a notification when it's otherwise ready to continue the 278 | /// shutdown operation. When woken up this method should be called again. 279 | /// 280 | /// * `Err(e)` - indicates a fatal error has happened with shutdown, 281 | /// indicating that the shutdown operation did not complete successfully. 282 | /// This typically means that the I/O object is no longer usable. 283 | /// 284 | /// # Errors 285 | /// 286 | /// This function can return normal I/O errors through `Err`, described 287 | /// above. Additionally this method may also render the underlying 288 | /// `Write::write` method no longer usable (e.g. will return errors in the 289 | /// future). It's recommended that once `shutdown` is called the 290 | /// `write` method is no longer called. 291 | /// 292 | /// # Panics 293 | /// 294 | /// This function will panic if not called within the context of a future's 295 | /// task. 296 | fn shutdown(&mut self) -> Poll<(), std_io::Error>; 297 | 298 | /// Write a `Buf` into this value, returning how many bytes were written. 299 | /// 300 | /// Note that this method will advance the `buf` provided automatically by 301 | /// the number of bytes written. 302 | fn write_buf(&mut self, buf: &mut B) -> Poll 303 | where Self: Sized, 304 | { 305 | if !buf.has_remaining() { 306 | return Ok(Async::Ready(0)); 307 | } 308 | 309 | let n = try_nb!(self.write(buf.bytes())); 310 | buf.advance(n); 311 | Ok(Async::Ready(n)) 312 | } 313 | } 314 | 315 | impl AsyncWrite for Box { 316 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 317 | (**self).shutdown() 318 | } 319 | } 320 | impl<'a, T: ?Sized + AsyncWrite> AsyncWrite for &'a mut T { 321 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 322 | (**self).shutdown() 323 | } 324 | } 325 | 326 | impl AsyncRead for std_io::Repeat { 327 | unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { 328 | false 329 | } 330 | } 331 | 332 | impl AsyncWrite for std_io::Sink { 333 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 334 | Ok(().into()) 335 | } 336 | } 337 | 338 | // TODO: Implement `prepare_uninitialized_buffer` for `io::Take`. 339 | // This is blocked on rust-lang/rust#27269 340 | impl AsyncRead for std_io::Take { 341 | } 342 | 343 | // TODO: Implement `prepare_uninitialized_buffer` when upstream exposes inner 344 | // parts 345 | impl AsyncRead for std_io::Chain 346 | where T: AsyncRead, 347 | U: AsyncRead, 348 | { 349 | } 350 | 351 | impl AsyncWrite for std_io::BufWriter { 352 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 353 | try_nb!(self.flush()); 354 | self.get_mut().shutdown() 355 | } 356 | } 357 | 358 | impl AsyncRead for std_io::BufReader { 359 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 360 | self.get_ref().prepare_uninitialized_buffer(buf) 361 | } 362 | } 363 | 364 | impl> AsyncRead for std_io::Cursor { 365 | } 366 | 367 | impl<'a> AsyncWrite for std_io::Cursor<&'a mut [u8]> { 368 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 369 | Ok(().into()) 370 | } 371 | } 372 | 373 | impl AsyncWrite for std_io::Cursor> { 374 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 375 | Ok(().into()) 376 | } 377 | } 378 | 379 | impl AsyncWrite for std_io::Cursor> { 380 | fn shutdown(&mut self) -> Poll<(), std_io::Error> { 381 | Ok(().into()) 382 | } 383 | } 384 | 385 | fn _assert_objects() { 386 | fn _assert() {} 387 | _assert::>(); 388 | _assert::>(); 389 | } 390 | -------------------------------------------------------------------------------- /tests/length_delimited.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio_io; 2 | extern crate futures; 3 | 4 | use tokio_io::{AsyncRead, AsyncWrite}; 5 | use tokio_io::codec::length_delimited::*; 6 | 7 | use futures::{Stream, Sink, Poll}; 8 | use futures::Async::*; 9 | 10 | use std::io; 11 | use std::collections::VecDeque; 12 | 13 | macro_rules! mock { 14 | ($($x:expr,)*) => {{ 15 | let mut v = VecDeque::new(); 16 | v.extend(vec![$($x),*]); 17 | Mock { calls: v } 18 | }}; 19 | } 20 | 21 | 22 | #[test] 23 | fn read_empty_io_yields_nothing() { 24 | let mut io = FramedRead::new(mock!()); 25 | 26 | assert_eq!(io.poll().unwrap(), Ready(None)); 27 | } 28 | 29 | #[test] 30 | fn read_single_frame_one_packet() { 31 | let mut io = FramedRead::new(mock! { 32 | Ok(b"\x00\x00\x00\x09abcdefghi"[..].into()), 33 | }); 34 | 35 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 36 | assert_eq!(io.poll().unwrap(), Ready(None)); 37 | } 38 | 39 | #[test] 40 | fn read_single_frame_one_packet_little_endian() { 41 | let mut io = Builder::new() 42 | .little_endian() 43 | .new_read(mock! { 44 | Ok(b"\x09\x00\x00\x00abcdefghi"[..].into()), 45 | }); 46 | 47 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 48 | assert_eq!(io.poll().unwrap(), Ready(None)); 49 | } 50 | 51 | #[test] 52 | fn read_single_multi_frame_one_packet() { 53 | let mut data: Vec = vec![]; 54 | data.extend_from_slice(b"\x00\x00\x00\x09abcdefghi"); 55 | data.extend_from_slice(b"\x00\x00\x00\x03123"); 56 | data.extend_from_slice(b"\x00\x00\x00\x0bhello world"); 57 | 58 | let mut io = FramedRead::new(mock! { 59 | Ok(data.into()), 60 | }); 61 | 62 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 63 | assert_eq!(io.poll().unwrap(), Ready(Some(b"123"[..].into()))); 64 | assert_eq!(io.poll().unwrap(), Ready(Some(b"hello world"[..].into()))); 65 | assert_eq!(io.poll().unwrap(), Ready(None)); 66 | } 67 | 68 | #[test] 69 | fn read_single_frame_multi_packet() { 70 | let mut io = FramedRead::new(mock! { 71 | Ok(b"\x00\x00"[..].into()), 72 | Ok(b"\x00\x09abc"[..].into()), 73 | Ok(b"defghi"[..].into()), 74 | }); 75 | 76 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 77 | assert_eq!(io.poll().unwrap(), Ready(None)); 78 | } 79 | 80 | #[test] 81 | fn read_multi_frame_multi_packet() { 82 | let mut io = FramedRead::new(mock! { 83 | Ok(b"\x00\x00"[..].into()), 84 | Ok(b"\x00\x09abc"[..].into()), 85 | Ok(b"defghi"[..].into()), 86 | Ok(b"\x00\x00\x00\x0312"[..].into()), 87 | Ok(b"3\x00\x00\x00\x0bhello world"[..].into()), 88 | }); 89 | 90 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 91 | assert_eq!(io.poll().unwrap(), Ready(Some(b"123"[..].into()))); 92 | assert_eq!(io.poll().unwrap(), Ready(Some(b"hello world"[..].into()))); 93 | assert_eq!(io.poll().unwrap(), Ready(None)); 94 | } 95 | 96 | #[test] 97 | fn read_single_frame_multi_packet_wait() { 98 | let mut io = FramedRead::new(mock! { 99 | Ok(b"\x00\x00"[..].into()), 100 | Err(would_block()), 101 | Ok(b"\x00\x09abc"[..].into()), 102 | Err(would_block()), 103 | Ok(b"defghi"[..].into()), 104 | Err(would_block()), 105 | }); 106 | 107 | assert_eq!(io.poll().unwrap(), NotReady); 108 | assert_eq!(io.poll().unwrap(), NotReady); 109 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 110 | assert_eq!(io.poll().unwrap(), NotReady); 111 | assert_eq!(io.poll().unwrap(), Ready(None)); 112 | } 113 | 114 | #[test] 115 | fn read_multi_frame_multi_packet_wait() { 116 | let mut io = FramedRead::new(mock! { 117 | Ok(b"\x00\x00"[..].into()), 118 | Err(would_block()), 119 | Ok(b"\x00\x09abc"[..].into()), 120 | Err(would_block()), 121 | Ok(b"defghi"[..].into()), 122 | Err(would_block()), 123 | Ok(b"\x00\x00\x00\x0312"[..].into()), 124 | Err(would_block()), 125 | Ok(b"3\x00\x00\x00\x0bhello world"[..].into()), 126 | Err(would_block()), 127 | }); 128 | 129 | 130 | assert_eq!(io.poll().unwrap(), NotReady); 131 | assert_eq!(io.poll().unwrap(), NotReady); 132 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 133 | assert_eq!(io.poll().unwrap(), NotReady); 134 | assert_eq!(io.poll().unwrap(), NotReady); 135 | assert_eq!(io.poll().unwrap(), Ready(Some(b"123"[..].into()))); 136 | assert_eq!(io.poll().unwrap(), Ready(Some(b"hello world"[..].into()))); 137 | assert_eq!(io.poll().unwrap(), NotReady); 138 | assert_eq!(io.poll().unwrap(), Ready(None)); 139 | } 140 | 141 | #[test] 142 | fn read_incomplete_head() { 143 | let mut io = FramedRead::new(mock! { 144 | Ok(b"\x00\x00"[..].into()), 145 | }); 146 | 147 | assert!(io.poll().is_err()); 148 | } 149 | 150 | #[test] 151 | fn read_incomplete_head_multi() { 152 | let mut io = FramedRead::new(mock! { 153 | Err(would_block()), 154 | Ok(b"\x00"[..].into()), 155 | Err(would_block()), 156 | }); 157 | 158 | assert_eq!(io.poll().unwrap(), NotReady); 159 | assert_eq!(io.poll().unwrap(), NotReady); 160 | assert!(io.poll().is_err()); 161 | } 162 | 163 | #[test] 164 | fn read_incomplete_payload() { 165 | let mut io = FramedRead::new(mock! { 166 | Ok(b"\x00\x00\x00\x09ab"[..].into()), 167 | Err(would_block()), 168 | Ok(b"cd"[..].into()), 169 | Err(would_block()), 170 | }); 171 | 172 | assert_eq!(io.poll().unwrap(), NotReady); 173 | assert_eq!(io.poll().unwrap(), NotReady); 174 | assert!(io.poll().is_err()); 175 | } 176 | 177 | #[test] 178 | fn read_max_frame_len() { 179 | let mut io = Builder::new() 180 | .max_frame_length(5) 181 | .new_read(mock! { 182 | Ok(b"\x00\x00\x00\x09abcdefghi"[..].into()), 183 | }); 184 | 185 | assert_eq!(io.poll().unwrap_err().kind(), io::ErrorKind::InvalidData); 186 | } 187 | 188 | #[test] 189 | fn read_update_max_frame_len_at_rest() { 190 | let mut io = Builder::new() 191 | .new_read(mock! { 192 | Ok(b"\x00\x00\x00\x09abcdefghi"[..].into()), 193 | Ok(b"\x00\x00\x00\x09abcdefghi"[..].into()), 194 | }); 195 | 196 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 197 | io.set_max_frame_length(5); 198 | assert_eq!(io.poll().unwrap_err().kind(), io::ErrorKind::InvalidData); 199 | } 200 | 201 | #[test] 202 | fn read_update_max_frame_len_in_flight() { 203 | let mut io = Builder::new() 204 | .new_read(mock! { 205 | Ok(b"\x00\x00\x00\x09abcd"[..].into()), 206 | Err(would_block()), 207 | Ok(b"efghi"[..].into()), 208 | Ok(b"\x00\x00\x00\x09abcdefghi"[..].into()), 209 | }); 210 | 211 | assert_eq!(io.poll().unwrap(), NotReady); 212 | io.set_max_frame_length(5); 213 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 214 | assert_eq!(io.poll().unwrap_err().kind(), io::ErrorKind::InvalidData); 215 | } 216 | 217 | #[test] 218 | fn read_one_byte_length_field() { 219 | let mut io = Builder::new() 220 | .length_field_length(1) 221 | .new_read(mock! { 222 | Ok(b"\x09abcdefghi"[..].into()), 223 | }); 224 | 225 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 226 | assert_eq!(io.poll().unwrap(), Ready(None)); 227 | } 228 | 229 | #[test] 230 | fn read_header_offset() { 231 | let mut io = Builder::new() 232 | .length_field_length(2) 233 | .length_field_offset(4) 234 | .new_read(mock! { 235 | Ok(b"zzzz\x00\x09abcdefghi"[..].into()), 236 | }); 237 | 238 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 239 | assert_eq!(io.poll().unwrap(), Ready(None)); 240 | } 241 | 242 | #[test] 243 | fn read_single_multi_frame_one_packet_skip_none_adjusted() { 244 | let mut data: Vec = vec![]; 245 | data.extend_from_slice(b"xx\x00\x09abcdefghi"); 246 | data.extend_from_slice(b"yy\x00\x03123"); 247 | data.extend_from_slice(b"zz\x00\x0bhello world"); 248 | 249 | let mut io = Builder::new() 250 | .length_field_length(2) 251 | .length_field_offset(2) 252 | .num_skip(0) 253 | .length_adjustment(4) 254 | .new_read(mock! { 255 | Ok(data.into()), 256 | }); 257 | 258 | assert_eq!(io.poll().unwrap(), Ready(Some(b"xx\x00\x09abcdefghi"[..].into()))); 259 | assert_eq!(io.poll().unwrap(), Ready(Some(b"yy\x00\x03123"[..].into()))); 260 | assert_eq!(io.poll().unwrap(), Ready(Some(b"zz\x00\x0bhello world"[..].into()))); 261 | assert_eq!(io.poll().unwrap(), Ready(None)); 262 | } 263 | 264 | #[test] 265 | fn read_single_multi_frame_one_packet_length_includes_head() { 266 | let mut data: Vec = vec![]; 267 | data.extend_from_slice(b"\x00\x0babcdefghi"); 268 | data.extend_from_slice(b"\x00\x05123"); 269 | data.extend_from_slice(b"\x00\x0dhello world"); 270 | 271 | let mut io = Builder::new() 272 | .length_field_length(2) 273 | .length_adjustment(-2) 274 | .new_read(mock! { 275 | Ok(data.into()), 276 | }); 277 | 278 | assert_eq!(io.poll().unwrap(), Ready(Some(b"abcdefghi"[..].into()))); 279 | assert_eq!(io.poll().unwrap(), Ready(Some(b"123"[..].into()))); 280 | assert_eq!(io.poll().unwrap(), Ready(Some(b"hello world"[..].into()))); 281 | assert_eq!(io.poll().unwrap(), Ready(None)); 282 | } 283 | 284 | #[test] 285 | fn write_single_frame_length_adjusted() { 286 | let mut io = Builder::new() 287 | .length_adjustment(-2) 288 | .new_write(mock! { 289 | Ok(b"\x00\x00\x00\x0b"[..].into()), 290 | Ok(b"abcdefghi"[..].into()), 291 | Ok(Flush), 292 | }); 293 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 294 | assert!(io.poll_complete().unwrap().is_ready()); 295 | assert!(io.get_ref().calls.is_empty()); 296 | } 297 | 298 | #[test] 299 | fn write_nothing_yields_nothing() { 300 | let mut io: FramedWrite<_, &'static [u8]> = FramedWrite::new(mock!()); 301 | assert!(io.poll_complete().unwrap().is_ready()); 302 | } 303 | 304 | #[test] 305 | fn write_single_frame_one_packet() { 306 | let mut io = FramedWrite::new(mock! { 307 | Ok(b"\x00\x00\x00\x09"[..].into()), 308 | Ok(b"abcdefghi"[..].into()), 309 | Ok(Flush), 310 | }); 311 | 312 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 313 | assert!(io.poll_complete().unwrap().is_ready()); 314 | assert!(io.get_ref().calls.is_empty()); 315 | } 316 | 317 | #[test] 318 | fn write_single_multi_frame_one_packet() { 319 | let mut io = FramedWrite::new(mock! { 320 | Ok(b"\x00\x00\x00\x09"[..].into()), 321 | Ok(b"abcdefghi"[..].into()), 322 | Ok(b"\x00\x00\x00\x03"[..].into()), 323 | Ok(b"123"[..].into()), 324 | Ok(b"\x00\x00\x00\x0b"[..].into()), 325 | Ok(b"hello world"[..].into()), 326 | Ok(Flush), 327 | }); 328 | 329 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 330 | assert!(io.start_send("123").unwrap().is_ready()); 331 | assert!(io.start_send("hello world").unwrap().is_ready()); 332 | assert!(io.poll_complete().unwrap().is_ready()); 333 | assert!(io.get_ref().calls.is_empty()); 334 | } 335 | 336 | #[test] 337 | fn write_single_multi_frame_multi_packet() { 338 | let mut io = FramedWrite::new(mock! { 339 | Ok(b"\x00\x00\x00\x09"[..].into()), 340 | Ok(b"abcdefghi"[..].into()), 341 | Ok(Flush), 342 | Ok(b"\x00\x00\x00\x03"[..].into()), 343 | Ok(b"123"[..].into()), 344 | Ok(Flush), 345 | Ok(b"\x00\x00\x00\x0b"[..].into()), 346 | Ok(b"hello world"[..].into()), 347 | Ok(Flush), 348 | }); 349 | 350 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 351 | assert!(io.poll_complete().unwrap().is_ready()); 352 | assert!(io.start_send("123").unwrap().is_ready()); 353 | assert!(io.poll_complete().unwrap().is_ready()); 354 | assert!(io.start_send("hello world").unwrap().is_ready()); 355 | assert!(io.poll_complete().unwrap().is_ready()); 356 | assert!(io.get_ref().calls.is_empty()); 357 | } 358 | 359 | #[test] 360 | fn write_single_frame_would_block() { 361 | let mut io = FramedWrite::new(mock! { 362 | Err(would_block()), 363 | Ok(b"\x00\x00"[..].into()), 364 | Err(would_block()), 365 | Ok(b"\x00\x09"[..].into()), 366 | Ok(b"abcdefghi"[..].into()), 367 | Ok(Flush), 368 | }); 369 | 370 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 371 | assert!(!io.poll_complete().unwrap().is_ready()); 372 | assert!(!io.poll_complete().unwrap().is_ready()); 373 | assert!(io.poll_complete().unwrap().is_ready()); 374 | 375 | assert!(io.get_ref().calls.is_empty()); 376 | } 377 | 378 | #[test] 379 | fn write_single_frame_little_endian() { 380 | let mut io = Builder::new() 381 | .little_endian() 382 | .new_write(mock! { 383 | Ok(b"\x09\x00\x00\x00"[..].into()), 384 | Ok(b"abcdefghi"[..].into()), 385 | Ok(Flush), 386 | }); 387 | 388 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 389 | assert!(io.poll_complete().unwrap().is_ready()); 390 | assert!(io.get_ref().calls.is_empty()); 391 | } 392 | 393 | 394 | #[test] 395 | fn write_single_frame_with_short_length_field() { 396 | let mut io = Builder::new() 397 | .length_field_length(1) 398 | .new_write(mock! { 399 | Ok(b"\x09"[..].into()), 400 | Ok(b"abcdefghi"[..].into()), 401 | Ok(Flush), 402 | }); 403 | 404 | assert!(io.start_send("abcdefghi").unwrap().is_ready()); 405 | assert!(io.poll_complete().unwrap().is_ready()); 406 | assert!(io.get_ref().calls.is_empty()); 407 | } 408 | 409 | #[test] 410 | fn write_max_frame_len() { 411 | let mut io = Builder::new() 412 | .max_frame_length(5) 413 | .new_write(mock! { }); 414 | 415 | assert_eq!(io.start_send("abcdef").unwrap_err().kind(), io::ErrorKind::InvalidInput); 416 | assert!(io.get_ref().calls.is_empty()); 417 | } 418 | 419 | #[test] 420 | fn write_update_max_frame_len_at_rest() { 421 | let mut io = Builder::new() 422 | .new_write(mock! { 423 | Ok(b"\x00\x00\x00\x06"[..].into()), 424 | Ok(b"abcdef"[..].into()), 425 | Ok(Flush), 426 | }); 427 | 428 | assert!(io.start_send("abcdef").unwrap().is_ready()); 429 | assert!(io.poll_complete().unwrap().is_ready()); 430 | io.set_max_frame_length(5); 431 | assert_eq!(io.start_send("abcdef").unwrap_err().kind(), io::ErrorKind::InvalidInput); 432 | assert!(io.get_ref().calls.is_empty()); 433 | } 434 | 435 | #[test] 436 | fn write_update_max_frame_len_in_flight() { 437 | let mut io = Builder::new() 438 | .new_write(mock! { 439 | Ok(b"\x00\x00\x00\x06"[..].into()), 440 | Ok(b"ab"[..].into()), 441 | Err(would_block()), 442 | Ok(b"cdef"[..].into()), 443 | Ok(Flush), 444 | }); 445 | 446 | assert!(io.start_send("abcdef").unwrap().is_ready()); 447 | assert!(!io.poll_complete().unwrap().is_ready()); 448 | io.set_max_frame_length(5); 449 | assert!(io.poll_complete().unwrap().is_ready()); 450 | assert_eq!(io.start_send("abcdef").unwrap_err().kind(), io::ErrorKind::InvalidInput); 451 | assert!(io.get_ref().calls.is_empty()); 452 | } 453 | 454 | // ===== Test utils ===== 455 | 456 | fn would_block() -> io::Error { 457 | io::Error::new(io::ErrorKind::WouldBlock, "would block") 458 | } 459 | 460 | struct Mock { 461 | calls: VecDeque>, 462 | } 463 | 464 | enum Op { 465 | Data(Vec), 466 | Flush, 467 | } 468 | 469 | use self::Op::*; 470 | 471 | impl io::Read for Mock { 472 | fn read(&mut self, dst: &mut [u8]) -> io::Result { 473 | match self.calls.pop_front() { 474 | Some(Ok(Op::Data(data))) => { 475 | debug_assert!(dst.len() >= data.len()); 476 | dst[..data.len()].copy_from_slice(&data[..]); 477 | Ok(data.len()) 478 | } 479 | Some(Ok(_)) => panic!(), 480 | Some(Err(e)) => Err(e), 481 | None => Ok(0), 482 | } 483 | } 484 | } 485 | 486 | impl AsyncRead for Mock { 487 | } 488 | 489 | impl io::Write for Mock { 490 | fn write(&mut self, src: &[u8]) -> io::Result { 491 | match self.calls.pop_front() { 492 | Some(Ok(Op::Data(data))) => { 493 | let len = data.len(); 494 | assert!(src.len() >= len, "expect={:?}; actual={:?}", data, src); 495 | assert_eq!(&data[..], &src[..len]); 496 | Ok(len) 497 | } 498 | Some(Ok(_)) => panic!(), 499 | Some(Err(e)) => Err(e), 500 | None => Ok(0), 501 | } 502 | } 503 | 504 | fn flush(&mut self) -> io::Result<()> { 505 | match self.calls.pop_front() { 506 | Some(Ok(Op::Flush)) => { 507 | Ok(()) 508 | } 509 | Some(Ok(_)) => panic!(), 510 | Some(Err(e)) => Err(e), 511 | None => Ok(()), 512 | } 513 | } 514 | } 515 | 516 | impl AsyncWrite for Mock { 517 | fn shutdown(&mut self) -> Poll<(), io::Error> { 518 | Ok(Ready(())) 519 | } 520 | } 521 | 522 | impl<'a> From<&'a [u8]> for Op { 523 | fn from(src: &'a [u8]) -> Op { 524 | Op::Data(src.into()) 525 | } 526 | } 527 | 528 | impl From> for Op { 529 | fn from(src: Vec) -> Op { 530 | Op::Data(src) 531 | } 532 | } 533 | -------------------------------------------------------------------------------- /src/length_delimited.rs: -------------------------------------------------------------------------------- 1 | use {codec, AsyncRead, AsyncWrite}; 2 | 3 | use bytes::{Buf, BufMut, BytesMut, IntoBuf, BigEndian, LittleEndian}; 4 | use bytes::buf::Chain; 5 | 6 | use futures::{Async, AsyncSink, Stream, Sink, StartSend, Poll}; 7 | 8 | use std::{cmp, fmt}; 9 | use std::error::Error as StdError; 10 | use std::io::{self, Cursor}; 11 | 12 | /// Configure length delimited `FramedRead`, `FramedWrite`, and `Framed` values. 13 | /// 14 | /// `Builder` enables constructing configured length delimited framers. Note 15 | /// that not all configuration settings apply to both encoding and decoding. See 16 | /// the documentation for specific methods for more detail. 17 | #[derive(Debug, Clone, Copy)] 18 | pub struct Builder { 19 | // Maximum frame length 20 | max_frame_len: usize, 21 | 22 | // Number of bytes representing the field length 23 | length_field_len: usize, 24 | 25 | // Number of bytes in the header before the length field 26 | length_field_offset: usize, 27 | 28 | // Adjust the length specified in the header field by this amount 29 | length_adjustment: isize, 30 | 31 | // Total number of bytes to skip before reading the payload, if not set, 32 | // `length_field_len + length_field_offset` 33 | num_skip: Option, 34 | 35 | // Length field byte order (little or big endian) 36 | length_field_is_big_endian: bool, 37 | } 38 | 39 | /// Adapts a byte stream into a unified `Stream` and `Sink` that works over 40 | /// entire frame values. 41 | /// 42 | /// See [module level] documentation for more detail. 43 | /// 44 | /// [module level]: index.html 45 | pub struct Framed { 46 | inner: FramedRead>, 47 | } 48 | 49 | /// Adapts a byte stream to a `Stream` yielding entire frame values. 50 | /// 51 | /// See [module level] documentation for more detail. 52 | /// 53 | /// [module level]: index.html 54 | #[derive(Debug)] 55 | pub struct FramedRead { 56 | inner: codec::FramedRead, 57 | } 58 | 59 | /// An error when the number of bytes read is more than max frame length. 60 | pub struct FrameTooBig { 61 | _priv: (), 62 | } 63 | 64 | #[derive(Debug)] 65 | struct Decoder { 66 | // Configuration values 67 | builder: Builder, 68 | 69 | // Read state 70 | state: DecodeState, 71 | } 72 | 73 | #[derive(Debug, Clone, Copy)] 74 | enum DecodeState { 75 | Head, 76 | Data(usize), 77 | } 78 | 79 | /// Adapts a byte stream to a `Sink` accepting entire frame values. 80 | /// 81 | /// See [module level] documentation for more detail. 82 | /// 83 | /// [module level]: index.html 84 | pub struct FramedWrite { 85 | // I/O type 86 | inner: T, 87 | 88 | // Configuration values 89 | builder: Builder, 90 | 91 | // Current frame being written 92 | frame: Option, B::Buf>>, 93 | } 94 | 95 | // ===== impl Framed ===== 96 | 97 | impl Framed { 98 | /// Creates a new `Framed` with default configuration values. 99 | pub fn new(inner: T) -> Framed { 100 | Builder::new().new_framed(inner) 101 | } 102 | } 103 | 104 | impl Framed { 105 | /// Returns a reference to the underlying I/O stream wrapped by `Framed`. 106 | /// 107 | /// Note that care should be taken to not tamper with the underlying stream 108 | /// of data coming in as it may corrupt the stream of frames otherwise 109 | /// being worked with. 110 | pub fn get_ref(&self) -> &T { 111 | self.inner.get_ref().get_ref() 112 | } 113 | 114 | /// Returns a mutable reference to the underlying I/O stream wrapped by 115 | /// `Framed`. 116 | /// 117 | /// Note that care should be taken to not tamper with the underlying stream 118 | /// of data coming in as it may corrupt the stream of frames otherwise being 119 | /// worked with. 120 | pub fn get_mut(&mut self) -> &mut T { 121 | self.inner.get_mut().get_mut() 122 | } 123 | 124 | /// Consumes the `Framed`, returning its underlying I/O stream. 125 | /// 126 | /// Note that care should be taken to not tamper with the underlying stream 127 | /// of data coming in as it may corrupt the stream of frames otherwise being 128 | /// worked with. 129 | pub fn into_inner(self) -> T { 130 | self.inner.into_inner().into_inner() 131 | } 132 | } 133 | 134 | impl Stream for Framed { 135 | type Item = BytesMut; 136 | type Error = io::Error; 137 | 138 | fn poll(&mut self) -> Poll, io::Error> { 139 | self.inner.poll() 140 | } 141 | } 142 | 143 | impl Sink for Framed { 144 | type SinkItem = B; 145 | type SinkError = io::Error; 146 | 147 | fn start_send(&mut self, item: B) -> StartSend { 148 | self.inner.start_send(item) 149 | } 150 | 151 | fn poll_complete(&mut self) -> Poll<(), io::Error> { 152 | self.inner.poll_complete() 153 | } 154 | 155 | fn close(&mut self) -> Poll<(), io::Error> { 156 | self.inner.close() 157 | } 158 | } 159 | 160 | impl fmt::Debug for Framed 161 | where T: fmt::Debug, 162 | B::Buf: fmt::Debug, 163 | { 164 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 165 | f.debug_struct("Framed") 166 | .field("inner", &self.inner) 167 | .finish() 168 | } 169 | } 170 | 171 | // ===== impl FramedRead ===== 172 | 173 | impl FramedRead { 174 | /// Creates a new `FramedRead` with default configuration values. 175 | pub fn new(inner: T) -> FramedRead { 176 | Builder::new().new_read(inner) 177 | } 178 | } 179 | 180 | impl FramedRead { 181 | /// Returns the current max frame setting 182 | /// 183 | /// This is the largest size this codec will accept from the wire. Larger 184 | /// frames will be rejected. 185 | pub fn max_frame_length(&self) -> usize { 186 | self.inner.decoder().builder.max_frame_len 187 | } 188 | 189 | /// Updates the max frame setting. 190 | /// 191 | /// The change takes effect the next time a frame is decoded. In other 192 | /// words, if a frame is currently in process of being decoded with a frame 193 | /// size greater than `val` but less than the max frame length in effect 194 | /// before calling this function, then the frame will be allowed. 195 | pub fn set_max_frame_length(&mut self, val: usize) { 196 | self.inner.decoder_mut().builder.max_frame_length(val); 197 | } 198 | 199 | /// Returns a reference to the underlying I/O stream wrapped by `FramedRead`. 200 | /// 201 | /// Note that care should be taken to not tamper with the underlying stream 202 | /// of data coming in as it may corrupt the stream of frames otherwise 203 | /// being worked with. 204 | pub fn get_ref(&self) -> &T { 205 | self.inner.get_ref() 206 | } 207 | 208 | /// Returns a mutable reference to the underlying I/O stream wrapped by 209 | /// `FramedRead`. 210 | /// 211 | /// Note that care should be taken to not tamper with the underlying stream 212 | /// of data coming in as it may corrupt the stream of frames otherwise being 213 | /// worked with. 214 | pub fn get_mut(&mut self) -> &mut T { 215 | self.inner.get_mut() 216 | } 217 | 218 | /// Consumes the `FramedRead`, returning its underlying I/O stream. 219 | /// 220 | /// Note that care should be taken to not tamper with the underlying stream 221 | /// of data coming in as it may corrupt the stream of frames otherwise being 222 | /// worked with. 223 | pub fn into_inner(self) -> T { 224 | self.inner.into_inner() 225 | } 226 | } 227 | 228 | impl Stream for FramedRead { 229 | type Item = BytesMut; 230 | type Error = io::Error; 231 | 232 | fn poll(&mut self) -> Poll, io::Error> { 233 | self.inner.poll() 234 | } 235 | } 236 | 237 | impl Sink for FramedRead { 238 | type SinkItem = T::SinkItem; 239 | type SinkError = T::SinkError; 240 | 241 | fn start_send(&mut self, item: T::SinkItem) -> StartSend { 242 | self.inner.start_send(item) 243 | } 244 | 245 | fn poll_complete(&mut self) -> Poll<(), T::SinkError> { 246 | self.inner.poll_complete() 247 | } 248 | 249 | fn close(&mut self) -> Poll<(), T::SinkError> { 250 | self.inner.close() 251 | } 252 | } 253 | 254 | impl io::Write for FramedRead { 255 | fn write(&mut self, src: &[u8]) -> io::Result { 256 | self.inner.get_mut().write(src) 257 | } 258 | 259 | fn flush(&mut self) -> io::Result<()> { 260 | self.inner.get_mut().flush() 261 | } 262 | } 263 | 264 | impl AsyncWrite for FramedRead { 265 | fn shutdown(&mut self) -> Poll<(), io::Error> { 266 | self.inner.get_mut().shutdown() 267 | } 268 | 269 | fn write_buf(&mut self, buf: &mut B) -> Poll { 270 | self.inner.get_mut().write_buf(buf) 271 | } 272 | } 273 | 274 | // ===== impl Decoder ====== 275 | 276 | impl Decoder { 277 | fn decode_head(&mut self, src: &mut BytesMut) -> io::Result> { 278 | let head_len = self.builder.num_head_bytes(); 279 | let field_len = self.builder.length_field_len; 280 | 281 | if src.len() < head_len { 282 | // Not enough data 283 | return Ok(None); 284 | } 285 | 286 | let n = { 287 | let mut src = Cursor::new(&mut *src); 288 | 289 | // Skip the required bytes 290 | src.advance(self.builder.length_field_offset); 291 | 292 | // match endianess 293 | let n = if self.builder.length_field_is_big_endian { 294 | src.get_uint::(field_len) 295 | } else { 296 | src.get_uint::(field_len) 297 | }; 298 | 299 | if n > self.builder.max_frame_len as u64 { 300 | return Err(io::Error::new(io::ErrorKind::InvalidData, FrameTooBig { 301 | _priv: (), 302 | })); 303 | } 304 | 305 | // The check above ensures there is no overflow 306 | let n = n as usize; 307 | 308 | // Adjust `n` with bounds checking 309 | let n = if self.builder.length_adjustment < 0 { 310 | n.checked_sub(-self.builder.length_adjustment as usize) 311 | } else { 312 | n.checked_add(self.builder.length_adjustment as usize) 313 | }; 314 | 315 | // Error handling 316 | match n { 317 | Some(n) => n, 318 | None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "provided length would overflow after adjustment")), 319 | } 320 | }; 321 | 322 | let num_skip = self.builder.get_num_skip(); 323 | 324 | if num_skip > 0 { 325 | let _ = src.split_to(num_skip); 326 | } 327 | 328 | // Ensure that the buffer has enough space to read the incoming 329 | // payload 330 | src.reserve(n); 331 | 332 | return Ok(Some(n)); 333 | } 334 | 335 | fn decode_data(&self, n: usize, src: &mut BytesMut) -> io::Result> { 336 | // At this point, the buffer has already had the required capacity 337 | // reserved. All there is to do is read. 338 | if src.len() < n { 339 | return Ok(None); 340 | } 341 | 342 | Ok(Some(src.split_to(n))) 343 | } 344 | } 345 | 346 | impl codec::Decoder for Decoder { 347 | type Item = BytesMut; 348 | type Error = io::Error; 349 | 350 | fn decode(&mut self, src: &mut BytesMut) -> io::Result> { 351 | let n = match self.state { 352 | DecodeState::Head => { 353 | match try!(self.decode_head(src)) { 354 | Some(n) => { 355 | self.state = DecodeState::Data(n); 356 | n 357 | } 358 | None => return Ok(None), 359 | } 360 | } 361 | DecodeState::Data(n) => n, 362 | }; 363 | 364 | match try!(self.decode_data(n, src)) { 365 | Some(data) => { 366 | // Update the decode state 367 | self.state = DecodeState::Head; 368 | 369 | // Make sure the buffer has enough space to read the next head 370 | src.reserve(self.builder.num_head_bytes()); 371 | 372 | Ok(Some(data)) 373 | } 374 | None => Ok(None), 375 | } 376 | } 377 | } 378 | 379 | // ===== impl FramedWrite ===== 380 | 381 | impl FramedWrite { 382 | /// Creates a new `FramedWrite` with default configuration values. 383 | pub fn new(inner: T) -> FramedWrite { 384 | Builder::new().new_write(inner) 385 | } 386 | } 387 | 388 | impl FramedWrite { 389 | /// Returns the current max frame setting 390 | /// 391 | /// This is the largest size this codec will write to the wire. Larger 392 | /// frames will be rejected. 393 | pub fn max_frame_length(&self) -> usize { 394 | self.builder.max_frame_len 395 | } 396 | 397 | /// Updates the max frame setting. 398 | /// 399 | /// The change takes effect the next time a frame is encoded. In other 400 | /// words, if a frame is currently in process of being encoded with a frame 401 | /// size greater than `val` but less than the max frame length in effect 402 | /// before calling this function, then the frame will be allowed. 403 | pub fn set_max_frame_length(&mut self, val: usize) { 404 | self.builder.max_frame_length(val); 405 | } 406 | 407 | /// Returns a reference to the underlying I/O stream wrapped by 408 | /// `FramedWrite`. 409 | /// 410 | /// Note that care should be taken to not tamper with the underlying stream 411 | /// of data coming in as it may corrupt the stream of frames otherwise 412 | /// being worked with. 413 | pub fn get_ref(&self) -> &T { 414 | &self.inner 415 | } 416 | 417 | /// Returns a mutable reference to the underlying I/O stream wrapped by 418 | /// `FramedWrite`. 419 | /// 420 | /// Note that care should be taken to not tamper with the underlying stream 421 | /// of data coming in as it may corrupt the stream of frames otherwise being 422 | /// worked with. 423 | pub fn get_mut(&mut self) -> &mut T { 424 | &mut self.inner 425 | } 426 | 427 | /// Consumes the `FramedWrite`, returning its underlying I/O stream. 428 | /// 429 | /// Note that care should be taken to not tamper with the underlying stream 430 | /// of data coming in as it may corrupt the stream of frames otherwise being 431 | /// worked with. 432 | pub fn into_inner(self) -> T { 433 | self.inner 434 | } 435 | } 436 | 437 | impl FramedWrite { 438 | // If there is a buffered frame, try to write it to `T` 439 | fn do_write(&mut self) -> Poll<(), io::Error> { 440 | if self.frame.is_none() { 441 | return Ok(Async::Ready(())); 442 | } 443 | 444 | loop { 445 | let frame = self.frame.as_mut().unwrap(); 446 | try_ready!(self.inner.write_buf(frame)); 447 | 448 | if !frame.has_remaining() { 449 | break; 450 | } 451 | } 452 | 453 | self.frame = None; 454 | 455 | Ok(Async::Ready(())) 456 | } 457 | 458 | fn set_frame(&mut self, buf: B::Buf) -> io::Result<()> { 459 | let mut head = BytesMut::with_capacity(8); 460 | let n = buf.remaining(); 461 | 462 | if n > self.builder.max_frame_len { 463 | return Err(io::Error::new(io::ErrorKind::InvalidInput, FrameTooBig { 464 | _priv: (), 465 | })); 466 | } 467 | 468 | // Adjust `n` with bounds checking 469 | let n = if self.builder.length_adjustment < 0 { 470 | n.checked_add(-self.builder.length_adjustment as usize) 471 | } else { 472 | n.checked_sub(self.builder.length_adjustment as usize) 473 | }; 474 | 475 | // Error handling 476 | let n = match n { 477 | Some(n) => n, 478 | None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "provided length would overflow after adjustment")), 479 | }; 480 | 481 | if self.builder.length_field_is_big_endian { 482 | head.put_uint::(n as u64, self.builder.length_field_len); 483 | } else { 484 | head.put_uint::(n as u64, self.builder.length_field_len); 485 | } 486 | 487 | debug_assert!(self.frame.is_none()); 488 | 489 | self.frame = Some(head.into_buf().chain(buf)); 490 | 491 | Ok(()) 492 | } 493 | } 494 | 495 | impl Sink for FramedWrite { 496 | type SinkItem = B; 497 | type SinkError = io::Error; 498 | 499 | fn start_send(&mut self, item: B) -> StartSend { 500 | if !try!(self.do_write()).is_ready() { 501 | return Ok(AsyncSink::NotReady(item)); 502 | } 503 | 504 | try!(self.set_frame(item.into_buf())); 505 | 506 | Ok(AsyncSink::Ready) 507 | } 508 | 509 | fn poll_complete(&mut self) -> Poll<(), io::Error> { 510 | // Write any buffered frame to T 511 | try_ready!(self.do_write()); 512 | 513 | // Try flushing the underlying IO 514 | try_nb!(self.inner.flush()); 515 | 516 | return Ok(Async::Ready(())); 517 | } 518 | 519 | fn close(&mut self) -> Poll<(), io::Error> { 520 | try_ready!(self.poll_complete()); 521 | self.inner.shutdown() 522 | } 523 | } 524 | 525 | impl Stream for FramedWrite { 526 | type Item = T::Item; 527 | type Error = T::Error; 528 | 529 | fn poll(&mut self) -> Poll, T::Error> { 530 | self.inner.poll() 531 | } 532 | } 533 | 534 | impl io::Read for FramedWrite { 535 | fn read(&mut self, dst: &mut [u8]) -> io::Result { 536 | self.get_mut().read(dst) 537 | } 538 | } 539 | 540 | impl AsyncRead for FramedWrite { 541 | fn read_buf(&mut self, buf: &mut B) -> Poll { 542 | self.get_mut().read_buf(buf) 543 | } 544 | 545 | unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { 546 | self.get_ref().prepare_uninitialized_buffer(buf) 547 | } 548 | } 549 | 550 | impl fmt::Debug for FramedWrite 551 | where T: fmt::Debug, 552 | B::Buf: fmt::Debug, 553 | { 554 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 555 | f.debug_struct("FramedWrite") 556 | .field("inner", &self.inner) 557 | .field("builder", &self.builder) 558 | .field("frame", &self.frame) 559 | .finish() 560 | } 561 | } 562 | 563 | // ===== impl Builder ===== 564 | 565 | impl Builder { 566 | /// Creates a new length delimited framer builder with default configuration 567 | /// values. 568 | /// 569 | /// # Examples 570 | /// 571 | /// ``` 572 | /// # use tokio_io::AsyncRead; 573 | /// use tokio_io::codec::length_delimited::Builder; 574 | /// 575 | /// # fn bind_read(io: T) { 576 | /// Builder::new() 577 | /// .length_field_offset(0) 578 | /// .length_field_length(2) 579 | /// .length_adjustment(0) 580 | /// .num_skip(0) 581 | /// .new_read(io); 582 | /// # } 583 | /// ``` 584 | pub fn new() -> Builder { 585 | Builder { 586 | // Default max frame length of 8MB 587 | max_frame_len: 8 * 1_024 * 1_024, 588 | 589 | // Default byte length of 4 590 | length_field_len: 4, 591 | 592 | // Default to the header field being at the start of the header. 593 | length_field_offset: 0, 594 | 595 | length_adjustment: 0, 596 | 597 | // Total number of bytes to skip before reading the payload, if not set, 598 | // `length_field_len + length_field_offset` 599 | num_skip: None, 600 | 601 | // Default to reading the length field in network (big) endian. 602 | length_field_is_big_endian: true, 603 | } 604 | } 605 | 606 | /// Read the length field as a big endian integer 607 | /// 608 | /// This is the default setting. 609 | /// 610 | /// This configuration option applies to both encoding and decoding. 611 | /// 612 | /// # Examples 613 | /// 614 | /// ``` 615 | /// # use tokio_io::AsyncRead; 616 | /// use tokio_io::codec::length_delimited::Builder; 617 | /// 618 | /// # fn bind_read(io: T) { 619 | /// Builder::new() 620 | /// .big_endian() 621 | /// .new_read(io); 622 | /// # } 623 | /// ``` 624 | pub fn big_endian(&mut self) -> &mut Self { 625 | self.length_field_is_big_endian = true; 626 | self 627 | } 628 | 629 | /// Read the length field as a little endian integer 630 | /// 631 | /// The default setting is big endian. 632 | /// 633 | /// This configuration option applies to both encoding and decoding. 634 | /// 635 | /// # Examples 636 | /// 637 | /// ``` 638 | /// # use tokio_io::AsyncRead; 639 | /// use tokio_io::codec::length_delimited::Builder; 640 | /// 641 | /// # fn bind_read(io: T) { 642 | /// Builder::new() 643 | /// .little_endian() 644 | /// .new_read(io); 645 | /// # } 646 | /// ``` 647 | pub fn little_endian(&mut self) -> &mut Self { 648 | self.length_field_is_big_endian = false; 649 | self 650 | } 651 | 652 | /// Sets the max frame length 653 | /// 654 | /// This configuration option applies to both encoding and decoding. The 655 | /// default value is 8MB. 656 | /// 657 | /// When decoding, the length field read from the byte stream is checked 658 | /// against this setting **before** any adjustments are applied. When 659 | /// encoding, the length of the submitted payload is checked against this 660 | /// setting. 661 | /// 662 | /// When frames exceed the max length, an `io::Error` with the custom value 663 | /// of the `FrameTooBig` type will be returned. 664 | /// 665 | /// # Examples 666 | /// 667 | /// ``` 668 | /// # use tokio_io::AsyncRead; 669 | /// use tokio_io::codec::length_delimited::Builder; 670 | /// 671 | /// # fn bind_read(io: T) { 672 | /// Builder::new() 673 | /// .max_frame_length(8 * 1024) 674 | /// .new_read(io); 675 | /// # } 676 | /// ``` 677 | pub fn max_frame_length(&mut self, val: usize) -> &mut Self { 678 | self.max_frame_len = val; 679 | self 680 | } 681 | 682 | /// Sets the number of bytes used to represent the length field 683 | /// 684 | /// The default value is `4`. The max value is `8`. 685 | /// 686 | /// This configuration option applies to both encoding and decoding. 687 | /// 688 | /// # Examples 689 | /// 690 | /// ``` 691 | /// # use tokio_io::AsyncRead; 692 | /// use tokio_io::codec::length_delimited::Builder; 693 | /// 694 | /// # fn bind_read(io: T) { 695 | /// Builder::new() 696 | /// .length_field_length(4) 697 | /// .new_read(io); 698 | /// # } 699 | /// ``` 700 | pub fn length_field_length(&mut self, val: usize) -> &mut Self { 701 | assert!(val > 0 && val <= 8, "invalid length field length"); 702 | self.length_field_len = val; 703 | self 704 | } 705 | 706 | /// Sets the number of bytes in the header before the length field 707 | /// 708 | /// This configuration option only applies to decoding. 709 | /// 710 | /// # Examples 711 | /// 712 | /// ``` 713 | /// # use tokio_io::AsyncRead; 714 | /// use tokio_io::codec::length_delimited::Builder; 715 | /// 716 | /// # fn bind_read(io: T) { 717 | /// Builder::new() 718 | /// .length_field_offset(1) 719 | /// .new_read(io); 720 | /// # } 721 | /// ``` 722 | pub fn length_field_offset(&mut self, val: usize) -> &mut Self { 723 | self.length_field_offset = val; 724 | self 725 | } 726 | 727 | /// Delta between the payload length specified in the header and the real 728 | /// payload length 729 | /// 730 | /// # Examples 731 | /// 732 | /// ``` 733 | /// # use tokio_io::AsyncRead; 734 | /// use tokio_io::codec::length_delimited::Builder; 735 | /// 736 | /// # fn bind_read(io: T) { 737 | /// Builder::new() 738 | /// .length_adjustment(-2) 739 | /// .new_read(io); 740 | /// # } 741 | /// ``` 742 | pub fn length_adjustment(&mut self, val: isize) -> &mut Self { 743 | self.length_adjustment = val; 744 | self 745 | } 746 | 747 | /// Sets the number of bytes to skip before reading the payload 748 | /// 749 | /// Default value is `length_field_len + length_field_offset` 750 | /// 751 | /// This configuration option only applies to decoding 752 | /// 753 | /// # Examples 754 | /// 755 | /// ``` 756 | /// # use tokio_io::AsyncRead; 757 | /// use tokio_io::codec::length_delimited::Builder; 758 | /// 759 | /// # fn bind_read(io: T) { 760 | /// Builder::new() 761 | /// .num_skip(4) 762 | /// .new_read(io); 763 | /// # } 764 | /// ``` 765 | pub fn num_skip(&mut self, val: usize) -> &mut Self { 766 | self.num_skip = Some(val); 767 | self 768 | } 769 | 770 | /// Create a configured length delimited `FramedRead` 771 | /// 772 | /// # Examples 773 | /// 774 | /// ``` 775 | /// # use tokio_io::AsyncRead; 776 | /// use tokio_io::codec::length_delimited::Builder; 777 | /// 778 | /// # fn bind_read(io: T) { 779 | /// Builder::new() 780 | /// .length_field_offset(0) 781 | /// .length_field_length(2) 782 | /// .length_adjustment(0) 783 | /// .num_skip(0) 784 | /// .new_read(io); 785 | /// # } 786 | /// ``` 787 | pub fn new_read(&self, upstream: T) -> FramedRead 788 | where T: AsyncRead, 789 | { 790 | FramedRead { 791 | inner: codec::FramedRead::new(upstream, Decoder { 792 | builder: *self, 793 | state: DecodeState::Head, 794 | }), 795 | } 796 | } 797 | 798 | /// Create a configured length delimited `FramedWrite` 799 | /// 800 | /// # Examples 801 | /// 802 | /// ``` 803 | /// # extern crate tokio_io; 804 | /// # extern crate bytes; 805 | /// # use tokio_io::AsyncWrite; 806 | /// # use tokio_io::codec::length_delimited; 807 | /// # use bytes::BytesMut; 808 | /// # fn write_frame(io: T) { 809 | /// # let _: length_delimited::FramedWrite = 810 | /// length_delimited::Builder::new() 811 | /// .length_field_length(2) 812 | /// .new_write(io); 813 | /// # } 814 | /// # pub fn main() {} 815 | /// ``` 816 | pub fn new_write(&self, inner: T) -> FramedWrite 817 | where T: AsyncWrite, 818 | B: IntoBuf, 819 | { 820 | FramedWrite { 821 | inner: inner, 822 | builder: *self, 823 | frame: None, 824 | } 825 | } 826 | 827 | /// Create a configured length delimited `Framed` 828 | /// 829 | /// # Examples 830 | /// 831 | /// ``` 832 | /// # extern crate tokio_io; 833 | /// # extern crate bytes; 834 | /// # use tokio_io::{AsyncRead, AsyncWrite}; 835 | /// # use tokio_io::codec::length_delimited; 836 | /// # use bytes::BytesMut; 837 | /// # fn write_frame(io: T) { 838 | /// # let _: length_delimited::Framed = 839 | /// length_delimited::Builder::new() 840 | /// .length_field_length(2) 841 | /// .new_framed(io); 842 | /// # } 843 | /// # pub fn main() {} 844 | /// ``` 845 | pub fn new_framed(&self, inner: T) -> Framed 846 | where T: AsyncRead + AsyncWrite, 847 | B: IntoBuf 848 | { 849 | let inner = self.new_read(self.new_write(inner)); 850 | Framed { inner: inner } 851 | } 852 | 853 | fn num_head_bytes(&self) -> usize { 854 | let num = self.length_field_offset + self.length_field_len; 855 | cmp::max(num, self.num_skip.unwrap_or(0)) 856 | } 857 | 858 | fn get_num_skip(&self) -> usize { 859 | self.num_skip.unwrap_or(self.length_field_offset + self.length_field_len) 860 | } 861 | } 862 | 863 | 864 | // ===== impl FrameTooBig ===== 865 | 866 | impl fmt::Debug for FrameTooBig { 867 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 868 | f.debug_struct("FrameTooBig") 869 | .finish() 870 | } 871 | } 872 | 873 | impl fmt::Display for FrameTooBig { 874 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 875 | f.write_str(self.description()) 876 | } 877 | } 878 | 879 | impl StdError for FrameTooBig { 880 | fn description(&self) -> &str { 881 | "frame size too big" 882 | } 883 | } 884 | --------------------------------------------------------------------------------