use crate::codec::decoder::Decoder; use crate::codec::encoder::Encoder; use bytes::{BufMut, Bytes, BytesMut}; use std::io; /// A simple [`Decoder`] and [`Encoder`] implementation that just ships bytes around. /// /// [`Decoder`]: crate::codec::Decoder /// [`Encoder`]: crate::codec::Encoder /// /// # Example /// /// Turn an [`AsyncRead`] into a stream of `Result<`[`BytesMut`]`, `[`Error`]`>`. /// /// [`AsyncRead`]: tokio::io::AsyncRead /// [`BytesMut`]: bytes::BytesMut /// [`Error`]: std::io::Error /// /// ``` /// # mod hidden { /// # #[allow(unused_imports)] /// use tokio::fs::File; /// # } /// use tokio::io::AsyncRead; /// use tokio_util::codec::{FramedRead, BytesCodec}; /// /// # enum File {} /// # impl File { /// # async fn open(_name: &str) -> Result { /// # use std::io::Cursor; /// # Ok(Cursor::new(vec![0, 1, 2, 3, 4, 5])) /// # } /// # } /// # /// # #[tokio::main(flavor = "current_thread")] /// # async fn main() -> Result<(), std::io::Error> { /// let my_async_read = File::open("filename.txt").await?; /// let my_stream_of_bytes = FramedRead::new(my_async_read, BytesCodec::new()); /// # Ok(()) /// # } /// ``` /// #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] pub struct BytesCodec(()); impl BytesCodec { /// Creates a new `BytesCodec` for shipping around raw bytes. pub fn new() -> BytesCodec { BytesCodec(()) } } impl Decoder for BytesCodec { type Item = BytesMut; type Error = io::Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { if !buf.is_empty() { let len = buf.len(); Ok(Some(buf.split_to(len))) } else { Ok(None) } } } impl Encoder for BytesCodec { type Error = io::Error; fn encode(&mut self, data: Bytes, buf: &mut BytesMut) -> Result<(), io::Error> { buf.reserve(data.len()); buf.put(data); Ok(()) } } impl Encoder for BytesCodec { type Error = io::Error; fn encode(&mut self, data: BytesMut, buf: &mut BytesMut) -> Result<(), io::Error> { buf.reserve(data.len()); buf.put(data); Ok(()) } }