diff --git a/CHANGELOG.md b/CHANGELOG.md index bf7961a..994c43d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.0] + +### Changed + +- Use GATs for `Encoder` trait to allow encoding of borrowed data. + See [PR 9](https://github.com/mxinden/asynchronous-codec/pull/9). + ## [0.6.2] ### Fixed diff --git a/Cargo.toml b/Cargo.toml index 87a02ca..dd96d84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "asynchronous-codec" edition = "2018" -version = "0.6.2" +version = "0.7.0" authors = ["Max Inden "] description = "Utilities for encoding and decoding frames using `async/await`" license = "MIT" diff --git a/src/codec/bytes.rs b/src/codec/bytes.rs index 6bcca2f..ac751f3 100644 --- a/src/codec/bytes.rs +++ b/src/codec/bytes.rs @@ -29,10 +29,10 @@ use std::io::Error; pub struct BytesCodec; impl Encoder for BytesCodec { - type Item = Bytes; + type Item<'a> = Bytes; type Error = Error; - fn encode(&mut self, src: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, src: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error> { dst.extend_from_slice(&src); Ok(()) } diff --git a/src/codec/cbor.rs b/src/codec/cbor.rs index 42286ec..df9f95c 100644 --- a/src/codec/cbor.rs +++ b/src/codec/cbor.rs @@ -141,10 +141,10 @@ where for<'de> Dec: Deserialize<'de> + 'static, for<'de> Enc: Serialize + 'static, { - type Item = Enc; + type Item<'a> = Enc; type Error = CborCodecError; - fn encode(&mut self, data: Self::Item, buf: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, data: Self::Item<'_>, buf: &mut BytesMut) -> Result<(), Self::Error> { // Encode cbor let j = serde_cbor::to_vec(&data)?; diff --git a/src/codec/json.rs b/src/codec/json.rs index 4bb675b..90083b4 100644 --- a/src/codec/json.rs +++ b/src/codec/json.rs @@ -138,10 +138,10 @@ where for<'de> Dec: Deserialize<'de> + 'static, for<'de> Enc: Serialize + 'static, { - type Item = Enc; + type Item<'a> = Enc; type Error = JsonCodecError; - fn encode(&mut self, data: Self::Item, buf: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, data: Self::Item<'_>, buf: &mut BytesMut) -> Result<(), Self::Error> { // Encode json let j = serde_json::to_string(&data)?; diff --git a/src/codec/length.rs b/src/codec/length.rs index 344f6b6..166e214 100644 --- a/src/codec/length.rs +++ b/src/codec/length.rs @@ -18,10 +18,10 @@ const U64_LENGTH: usize = std::mem::size_of::(); /// pub struct MyStringCodec(LengthCodec); /// /// impl Encoder for MyStringCodec { -/// type Item = String; +/// type Item<'a> = String; /// type Error = Error; /// -/// fn encode(&mut self, src: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { +/// fn encode(&mut self, src: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error> { /// let bytes = Bytes::from(src); /// self.0.encode(bytes, dst) /// } @@ -47,10 +47,10 @@ const U64_LENGTH: usize = std::mem::size_of::(); pub struct LengthCodec; impl Encoder for LengthCodec { - type Item = Bytes; + type Item<'a> = Bytes; type Error = Error; - fn encode(&mut self, src: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, src: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error> { dst.reserve(U64_LENGTH + src.len()); dst.put_u64(src.len() as u64); dst.extend_from_slice(&src); diff --git a/src/codec/lines.rs b/src/codec/lines.rs index f8bd823..b6f9c8b 100644 --- a/src/codec/lines.rs +++ b/src/codec/lines.rs @@ -21,10 +21,10 @@ use std::io::{Error, ErrorKind}; pub struct LinesCodec; impl Encoder for LinesCodec { - type Item = String; + type Item<'a> = String; type Error = Error; - fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, item: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error> { dst.reserve(item.len()); dst.put(item.as_bytes()); Ok(()) diff --git a/src/encoder.rs b/src/encoder.rs index 73f290e..bce4050 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -5,19 +5,50 @@ use std::io::Error; /// Encoding of messages as bytes, for use with `FramedWrite`. pub trait Encoder { /// The type of items consumed by `encode` - type Item; + type Item<'a>; /// The type of encoding errors. type Error: From; /// Encodes an item into the `BytesMut` provided by dst. - fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error>; + fn encode(&mut self, item: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error>; } impl Encoder for Fuse { - type Item = U::Item; + type Item<'a> = U::Item<'a>; type Error = U::Error; - fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { + fn encode(&mut self, item: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error> { self.u.encode(item, dst) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::FramedWrite; + use futures::executor::block_on; + use futures_util::SinkExt; + + #[test] + fn can_use_borrowed_data() { + let mut buf = Vec::new(); + + let mut write = FramedWrite::new(&mut buf, BorrowedCodec); + block_on(write.send(&[1, 2, 3, 4])).unwrap(); + + assert_eq!(buf, vec![1, 2, 3, 4]) + } + + struct BorrowedCodec; + + impl Encoder for BorrowedCodec { + type Item<'a> = &'a [u8]; + type Error = Error; + + fn encode(&mut self, item: Self::Item<'_>, dst: &mut BytesMut) -> Result<(), Self::Error> { + dst.extend_from_slice(item); + + Ok(()) + } + } +} diff --git a/src/framed.rs b/src/framed.rs index 850c880..cad524e 100644 --- a/src/framed.rs +++ b/src/framed.rs @@ -163,7 +163,7 @@ where } } -impl Sink for Framed +impl Sink> for Framed where T: AsyncWrite + Unpin, U: Encoder, @@ -173,7 +173,7 @@ where fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { self.project().inner.poll_ready(cx) } - fn start_send(self: Pin<&mut Self>, item: U::Item) -> Result<(), Self::Error> { + fn start_send(self: Pin<&mut Self>, item: U::Item<'_>) -> Result<(), Self::Error> { self.project().inner.start_send(item) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { diff --git a/src/framed_write.rs b/src/framed_write.rs index 012c660..33fd39f 100644 --- a/src/framed_write.rs +++ b/src/framed_write.rs @@ -140,7 +140,7 @@ where } } -impl Sink for FramedWrite +impl Sink> for FramedWrite where T: AsyncWrite + Unpin, E: Encoder, @@ -150,7 +150,7 @@ where fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { self.project().inner.poll_ready(cx) } - fn start_send(self: Pin<&mut Self>, item: E::Item) -> Result<(), Self::Error> { + fn start_send(self: Pin<&mut Self>, item: E::Item<'_>) -> Result<(), Self::Error> { self.project().inner.start_send(item) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { @@ -221,7 +221,7 @@ impl AsyncRead for FramedWrite2 { } } -impl Sink for FramedWrite2 +impl Sink> for FramedWrite2 where T: AsyncWrite + Encoder + Unpin, { @@ -241,7 +241,7 @@ where Poll::Ready(Ok(())) } - fn start_send(mut self: Pin<&mut Self>, item: T::Item) -> Result<(), Self::Error> { + fn start_send(mut self: Pin<&mut Self>, item: T::Item<'_>) -> Result<(), Self::Error> { let this = &mut *self; this.inner.encode(item, &mut this.buffer) }