transformable/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(missing_docs, warnings)]
3#![forbid(unsafe_code)]
4#![cfg_attr(not(any(feature = "std", test)), no_std)]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6#![cfg_attr(docsrs, allow(unused_attributes))]
7
8#[cfg(all(not(feature = "std"), feature = "alloc"))]
9extern crate alloc as std;
10
11#[cfg(feature = "std")]
12extern crate std;
13
14macro_rules! test_transformable {
15  ($ty: ty => $test_fn:ident($init: expr)) => {
16    #[test]
17    fn $test_fn() {
18      use crate::TestTransformable;
19
20      <$ty>::test_transformable(|| $init);
21    }
22  };
23}
24
25#[cfg(any(feature = "alloc", feature = "std"))]
26const MESSAGE_SIZE_LEN: usize = core::mem::size_of::<u32>();
27#[cfg(feature = "std")]
28const MAX_INLINED_BYTES: usize = 256;
29
30/// The type can transform its representation between structured and byte form.
31pub trait Transformable: Send + Sync + 'static {
32  /// The error type returned when encoding or decoding fails.
33  type Error: core::error::Error + Send + Sync + 'static;
34
35  /// Encodes the value into the given buffer for transmission.
36  ///
37  /// Returns the number of bytes written to the buffer.
38  fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error>;
39
40  /// Encodes the value into a vec for transmission.
41  #[cfg(any(feature = "alloc", feature = "std"))]
42  #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
43  fn encode_to_vec(&self) -> Result<::std::vec::Vec<u8>, Self::Error> {
44    let mut buf = ::std::vec![0u8; self.encoded_len()];
45    self.encode(&mut buf)?;
46    Ok(buf)
47  }
48
49  /// Encodes the value into the given writer for transmission.
50  #[cfg(feature = "std")]
51  #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
52  fn encode_to_writer<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
53    let encoded_len = self.encoded_len();
54    if encoded_len <= MAX_INLINED_BYTES {
55      let mut buf = [0u8; MAX_INLINED_BYTES];
56      let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
57      writer.write_all(&buf[..encoded_len]).map(|_| len)
58    } else {
59      let mut buf = ::std::vec![0u8; encoded_len];
60      let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
61      writer.write_all(&buf).map(|_| len)
62    }
63  }
64
65  /// Encodes the value into the given async writer for transmission.
66  #[cfg(feature = "async")]
67  #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
68  fn encode_to_async_writer<W: futures_util::io::AsyncWrite + Send + Unpin>(
69    &self,
70    writer: &mut W,
71  ) -> impl std::future::Future<Output = std::io::Result<usize>> + Send {
72    use futures_util::io::AsyncWriteExt;
73    async move {
74      let encoded_len = self.encoded_len();
75      if encoded_len <= MAX_INLINED_BYTES {
76        let mut buf = [0u8; MAX_INLINED_BYTES];
77        let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
78        writer.write_all(&buf[..encoded_len]).await.map(|_| len)
79      } else {
80        let mut buf = ::std::vec![0u8; encoded_len];
81        let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
82        writer.write_all(&buf).await.map(|_| len)
83      }
84    }
85  }
86
87  /// Returns the encoded length of the value.
88  /// This is used to pre-allocate a buffer for encoding.
89  fn encoded_len(&self) -> usize;
90
91  /// Decodes the value from the given buffer received over the wire.
92  ///
93  /// Returns the number of bytes read from the buffer and the struct.
94  fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
95  where
96    Self: Sized;
97
98  /// Decodes the value from the given reader received over the wire.
99  ///
100  /// Returns the number of bytes read from the reader and the struct.
101  #[cfg(feature = "std")]
102  #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
103  fn decode_from_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<(usize, Self)>
104  where
105    Self: Sized,
106  {
107    use byteorder::{ByteOrder, NetworkEndian};
108
109    let mut len = [0u8; MESSAGE_SIZE_LEN];
110    reader.read_exact(&mut len)?;
111    let msg_len = NetworkEndian::read_u32(&len) as usize;
112
113    if msg_len <= MAX_INLINED_BYTES {
114      let mut buf = [0u8; MAX_INLINED_BYTES];
115      buf[..MESSAGE_SIZE_LEN].copy_from_slice(&len);
116      reader.read_exact(&mut buf[MESSAGE_SIZE_LEN..msg_len])?;
117      Self::decode(&buf[..msg_len]).map_err(utils::invalid_data)
118    } else {
119      let mut buf = ::std::vec![0u8; msg_len];
120      buf[..MESSAGE_SIZE_LEN].copy_from_slice(&len);
121      reader.read_exact(&mut buf[MESSAGE_SIZE_LEN..])?;
122      Self::decode(&buf).map_err(utils::invalid_data)
123    }
124  }
125
126  /// Decodes the value from the given async reader received over the wire.
127  ///
128  /// Returns the number of bytes read from the reader and the struct.
129  #[cfg(feature = "async")]
130  #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
131  fn decode_from_async_reader<R: futures_util::io::AsyncRead + Send + Unpin>(
132    reader: &mut R,
133  ) -> impl std::future::Future<Output = std::io::Result<(usize, Self)>> + Send
134  where
135    Self: Sized,
136  {
137    use byteorder::{ByteOrder, NetworkEndian};
138    use futures_util::io::AsyncReadExt;
139
140    async move {
141      let mut len = [0u8; MESSAGE_SIZE_LEN];
142      reader.read_exact(&mut len).await?;
143      let msg_len = NetworkEndian::read_u32(&len) as usize;
144
145      if msg_len <= MAX_INLINED_BYTES {
146        let mut buf = [0u8; MAX_INLINED_BYTES];
147        buf[..MESSAGE_SIZE_LEN].copy_from_slice(&len);
148        reader
149          .read_exact(&mut buf[MESSAGE_SIZE_LEN..msg_len])
150          .await?;
151        Self::decode(&buf[..msg_len]).map_err(utils::invalid_data)
152      } else {
153        let mut buf = vec![0u8; msg_len];
154        buf[..MESSAGE_SIZE_LEN].copy_from_slice(&len);
155        reader.read_exact(&mut buf[MESSAGE_SIZE_LEN..]).await?;
156        Self::decode(&buf).map_err(utils::invalid_data)
157      }
158    }
159  }
160}
161
162/// The type can transform its representation to byte form.
163pub trait Encodable: Send + Sync {
164  /// The error type returned when encoding or decoding fails.
165  type Error: core::error::Error + Send + Sync + 'static;
166
167  /// Encodes the value into the given buffer for transmission.
168  ///
169  /// Returns the number of bytes written to the buffer.
170  fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error>;
171
172  /// Encodes the value into a vec for transmission.
173  #[cfg(any(feature = "alloc", feature = "std"))]
174  #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
175  fn encode_to_vec(&self) -> Result<::std::vec::Vec<u8>, Self::Error> {
176    let mut buf = ::std::vec![0u8; self.encoded_len()];
177    self.encode(&mut buf)?;
178    Ok(buf)
179  }
180
181  /// Encodes the value into the given writer for transmission.
182  #[cfg(feature = "std")]
183  #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
184  fn encode_to_writer<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
185    let encoded_len = self.encoded_len();
186    if encoded_len <= MAX_INLINED_BYTES {
187      let mut buf = [0u8; MAX_INLINED_BYTES];
188      let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
189      writer.write_all(&buf[..encoded_len]).map(|_| len)
190    } else {
191      let mut buf = ::std::vec![0u8; encoded_len];
192      let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
193      writer.write_all(&buf).map(|_| len)
194    }
195  }
196
197  /// Encodes the value into the given async writer for transmission.
198  #[cfg(feature = "async")]
199  #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
200  fn encode_to_async_writer<W: futures_util::io::AsyncWrite + Send + Unpin>(
201    &self,
202    writer: &mut W,
203  ) -> impl std::future::Future<Output = std::io::Result<usize>> + Send {
204    use futures_util::io::AsyncWriteExt;
205    async move {
206      let encoded_len = self.encoded_len();
207      if encoded_len <= MAX_INLINED_BYTES {
208        let mut buf = [0u8; MAX_INLINED_BYTES];
209        let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
210        writer.write_all(&buf[..encoded_len]).await.map(|_| len)
211      } else {
212        let mut buf = ::std::vec![0u8; encoded_len];
213        let len = self.encode(&mut buf).map_err(utils::invalid_data)?;
214        writer.write_all(&buf).await.map(|_| len)
215      }
216    }
217  }
218
219  /// Returns the encoded length of the value.
220  /// This is used to pre-allocate a buffer for encoding.
221  fn encoded_len(&self) -> usize;
222}
223
224impl<T: Transformable> Encodable for T {
225  type Error = T::Error;
226
227  fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error> {
228    Transformable::encode(self, dst)
229  }
230
231  fn encoded_len(&self) -> usize {
232    Transformable::encoded_len(self)
233  }
234
235  #[cfg(any(feature = "alloc", feature = "std"))]
236  fn encode_to_vec(&self) -> Result<::std::vec::Vec<u8>, Self::Error> {
237    Transformable::encode_to_vec(self)
238  }
239
240  #[cfg(feature = "std")]
241  fn encode_to_writer<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
242    Transformable::encode_to_writer(self, writer)
243  }
244
245  #[cfg(feature = "async")]
246  fn encode_to_async_writer<W: futures_util::io::AsyncWrite + Send + Unpin>(
247    &self,
248    writer: &mut W,
249  ) -> impl std::future::Future<Output = std::io::Result<usize>> + Send {
250    Transformable::encode_to_async_writer(self, writer)
251  }
252}
253
254/// The type can transform its representation from byte form to struct.
255pub trait Decodable: Send + 'static {
256  /// The error type returned when encoding or decoding fails.
257  type Error: core::error::Error + Send + Sync + 'static;
258
259  /// Decodes the value from the given buffer received over the wire.
260  ///
261  /// Returns the number of bytes read from the buffer and the struct.
262  fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
263  where
264    Self: Sized;
265
266  /// Decodes the value from the given reader received over the wire.
267  ///
268  /// Returns the number of bytes read from the reader and the struct.
269  #[cfg(feature = "std")]
270  #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
271  fn decode_from_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<(usize, Self)>
272  where
273    Self: Sized;
274
275  /// Decodes the value from the given async reader received over the wire.
276  ///
277  /// Returns the number of bytes read from the reader and the struct.
278  #[cfg(feature = "async")]
279  #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
280  fn decode_from_async_reader<R: futures_util::io::AsyncRead + Send + Unpin>(
281    reader: &mut R,
282  ) -> impl std::future::Future<Output = std::io::Result<(usize, Self)>> + Send
283  where
284    Self: Sized;
285}
286
287impl<T: Transformable> Decodable for T {
288  type Error = T::Error;
289
290  fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error> {
291    Transformable::decode(src)
292  }
293
294  #[cfg(feature = "std")]
295  fn decode_from_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<(usize, Self)>
296  where
297    Self: Sized,
298  {
299    Transformable::decode_from_reader(reader)
300  }
301
302  #[cfg(feature = "async")]
303  fn decode_from_async_reader<R: futures_util::io::AsyncRead + Send + Unpin>(
304    reader: &mut R,
305  ) -> impl std::future::Future<Output = std::io::Result<(usize, Self)>> + Send
306  where
307    Self: Sized + Send,
308  {
309    <Self as Transformable>::decode_from_async_reader::<R>(reader)
310  }
311}
312
313#[cfg(test)]
314trait TestTransformable: Transformable + Eq + core::fmt::Debug + Sized {
315  fn test_transformable(init: impl FnOnce() -> Self)
316  where
317    <Self as Transformable>::Error: core::error::Error + Send + Sync + 'static,
318  {
319    let val = init();
320    let mut buf = std::vec![0; val.encoded_len()];
321    val.encode(&mut buf).unwrap();
322    let (_, decoded) = Self::decode(&buf).unwrap();
323    assert_eq!(decoded, val);
324
325    #[cfg(feature = "std")]
326    {
327      let mut buf = std::vec::Vec::new();
328      val.encode_to_writer(&mut buf).unwrap();
329      let (_, decoded) = Self::decode_from_reader(&mut buf.as_slice()).unwrap();
330      assert_eq!(decoded, val);
331    }
332  }
333}
334
335#[cfg(test)]
336impl<T: Transformable + Eq + core::fmt::Debug + Sized> TestTransformable for T {}
337
338mod impls;
339pub use impls::*;
340
341/// Utilities for encoding and decoding.
342pub mod utils;