//! Sending and receiving serde-serialized structs. //! //! Currently structs are serialized with [`ssmarshal`][ssmarshal], //! but this is an implementation detail that may change without //! warning. `ssmarshal` uses a straightforward, compact serialization //! format that doesn't support compatibility between versions or //! dynamic length types (arrays, maps). Its lack of versioning fits //! with the design goals for the frame encoding in this crate: //! unsuitable for long-term storage or transmission between different //! versions of an application, but space-efficient. //! //! [ssmarshal]: https://crates.io/crates/ssmarshal //! //! ## Example usage from a `std` crate //! //! The `Sender` struct writes serialized and encoded values to an //! inner `std::io::Write` instance, and the `Receiver` struct reads //! and decodes values from an inner `std::io::Read` instance. //! //! ```rust //! # extern crate framed; //! # use framed::typed::*; //! # extern crate serde; //! # #[macro_use] //! # extern crate serde_derive; //! # //! # use std::io::Cursor; //! # //! # fn main() { //! #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] //! struct Test { //! a: u8, //! b: u16, //! } //! //! let payload = Test { a: 1, b: 2 }; //! //! let mut encoded = vec![]; //! { //! let mut sender = Sender::<_, Test>::new(&mut encoded); //! sender.send(&payload).expect("send ok"); //! } //! //! // `encoded` now contains the encoded value. //! //! let mut receiver = Receiver::<_, Test>::new(Cursor::new(encoded)); //! let decoded = receiver.recv().expect("recv ok"); //! //! assert_eq!(payload, decoded); //! # } //! ``` //! //! ## Example usage from a `no_std` crate //! //! The `encode_to_slice` and `decode_from_slice` functions offer an //! API for `no_std` crates that do not have a heap allocator and //! cannot use `std::io::Read` or `std::io::Write`. //! //! ```rust //! # extern crate framed; //! # use framed::typed::*; //! # extern crate serde; //! # #[macro_use] //! # extern crate serde_derive; //! # //! # fn main() { //! # #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] //! # struct Test { //! # a: u8, //! # b: u16, //! # } //! # //! # let payload = Test { a: 1, b: 2 }; //! # //! let mut ser_buf = [0u8; max_serialize_buf_len::()]; //! let mut encoded_buf = [0u8; max_encoded_len::()]; //! let encoded_len = encode_to_slice::( //! &payload, //! &mut ser_buf, //! &mut encoded_buf //! ).expect("encode ok"); //! let encoded = &encoded_buf[0..encoded_len]; //! //! // `encoded` now contains the complete encoded frame. //! //! let mut de_buf = [0u8; max_serialize_buf_len::()]; //! let decoded = decode_from_slice(encoded, &mut de_buf) //! .expect("decode ok"); //! //! assert_eq!(payload, decoded); //! # } //! ``` use ::{Encoded, TempBuffer}; use ::bytes; use ::error::{Result}; #[cfg(feature = "use_std")] use core::marker::PhantomData; use core::mem::size_of; use serde::Serialize; use serde::de::DeserializeOwned; use ssmarshal; #[cfg(feature = "use_std")] use std::io::{Read, Write}; /// Serializes and encodes the supplied value `v` into destination /// buffer `dest`, using `ser_buf` as a temporary serialization buffer. /// Available from `no_std` crates. /// /// Returns the number of bytes written to the beginning of `dest`. /// /// ## Panics /// /// This will panic if the supplied buffers are too small to serialize /// a value of `T`. Callers must ensure that: /// /// * `ser_buf.len() >= max_serialize_buf_len::()` and /// * `dest.len() >= max_encoded_len::()`. /// /// ## Examples /// /// See the [no_std usage example][ex] in the `typed` module documentation. /// [ex]: index.html#example-usage-from-a-no_std-crate pub fn encode_to_slice( v: &T, ser_buf: &mut TempBuffer, dest: &mut Encoded, ) -> Result { assert!(ser_buf.len() >= max_serialize_buf_len::()); assert!(dest.len() >= max_encoded_len::()); let ser_len = ssmarshal::serialize(ser_buf, v)?; let ser = &ser_buf[0..ser_len]; bytes::encode_to_slice(ser, dest) } /// Decodes the supplied encoded frame `e`, then deserializes its /// payload as a value of type `T`, using `de_buf` as a temporary /// deserialization buffer. Available from `no_std` crates. /// /// Returns the deserialized value. /// /// ## Panics /// /// This will panic if the supplied buffer is too small to deserialize /// a value of `T`. Callers must ensure that: /// /// * `de_buf.len() >= max_serialize_buf_len::()`. /// /// ## Examples /// /// See the [no_std usage example][ex] in the `typed` module documentation. /// [ex]: index.html#example-usage-from-a-no_std-crate pub fn decode_from_slice( e: &Encoded, de_buf: &mut TempBuffer ) -> Result { assert!(de_buf.len() >= max_serialize_buf_len::()); let de_len = bytes::decode_to_slice(e, de_buf)?; let payload = &de_buf[0..de_len]; let (v, _len) = ssmarshal::deserialize(payload)?; Ok(v) } const_fn! { /// Returns an upper bound for the encoded length of a frame with a /// serialized `T` value as its payload. /// /// Useful for calculating an appropriate buffer length. pub fn max_encoded_len() -> usize { bytes::max_encoded_len(max_serialize_buf_len::()) } } const_fn! { /// Returns an upper bound for the temporary serialization buffer /// length needed by `encode_to_slice` and `decode_from_slice` when /// serializing or deserializing a value of type `T`. pub fn max_serialize_buf_len() -> usize { bytes::max_encoded_len(size_of::()) } } /// Sends encoded structs of type `T` over an inner `std::io::Write` instance. /// /// ## Examples /// /// See the [std usage example][ex] in the `typed` module documentation. /// [ex]: index.html#example-usage-from-a-std-crate #[cfg(feature = "use_std")] pub struct Sender { w: W, _t: PhantomData, } #[cfg(feature = "use_std")] impl Sender { /// Construct a `Sender` that sends encoded structs over the supplied /// `io::Write`. pub fn new(w: W) -> Sender { Sender:: { w: w, _t: PhantomData::default(), } } /// Consume this `Sender` and return the inner `std::io::Write`. pub fn into_inner(self) -> W { self.w } /// Flush all buffered data. Includes calling `flush` on the inner /// writer. pub fn flush(&mut self) -> Result<()> { Ok(self.w.flush()?) } /// Queue the supplied payload for transmission. /// /// This `Sender` may buffer the data indefinitely, as may the /// inner writer. To ensure all buffered data has been /// transmitted call [`flush`](#method.flush). /// /// See also: [`send`](#method.send) pub fn queue(&mut self, v: &T) -> Result { // This uses a dynamically allocated buffer. // // I couldn't get a no_std version to compile with a stack-allocated // buffer as [0u8; size_of::()] due to compiler errors like: // ``` // error[E0401]: can't use type parameters from outer function; try using a local type parameter instead // --> src/typed.rs:46:39 // | // 46 | const _sbl: usize = size_of::(); // | ^ use of type variable from outer function // ``` // I think this may require const generics // (rust-lang tracking issue: // https://github.com/rust-lang/rust/issues/44580). let mut ser_buf = vec![0u8; size_of::()]; let ser_len = ssmarshal::serialize(&mut ser_buf, v)?; let ser = &ser_buf[0..ser_len]; bytes::encode_to_writer(&ser, &mut self.w) } /// Encode the supplied payload as a frame, write it to the /// inner writer, then flush. /// /// Ensures the data has been transmitted before returning to the /// caller. /// /// See also: [`queue`](#method.queue) pub fn send(&mut self, v: &T) -> Result { let len = self.queue(v)?; self.flush()?; Ok(len) } } /// Receives encoded structs of type `T` from an inner `std::io::Read` instance. /// /// ## Examples /// /// See the [std usage example][ex] in the `typed` module documentation. /// [ex]: index.html#example-usage-from-a-std-crate #[cfg(feature = "use_std")] pub struct Receiver { r: R, _t: PhantomData, } #[cfg(feature = "use_std")] impl Receiver { /// Construct a `Receiver` that receives encoded structs from the supplied /// `io::Read`. pub fn new(r: R) -> Receiver { Receiver:: { r: r, _t: PhantomData::default(), } } /// Consume this `Receiver` and return the inner `std::io::Read`. pub fn into_inner(self) -> R { self.r } /// Receive an encoded frame from the inner `std::io::Read`, decode it /// and return the payload. pub fn recv(&mut self) -> Result { let payload = bytes::decode_from_reader::(&mut self.r)?; let (v, _len) = ssmarshal::deserialize(&*payload)?; Ok(v) } } #[cfg(test)] mod tests { use super::*; #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] struct Test { i8: i8, i16: i16, i32: i32, i64: i64, u8: u8, u16: u16, u32: u32, u64: u64, some: Option, none: Option, a: [u8; 3], } fn test_val() -> Test { let v = Test { i8: 1, i16: 2, i32: 3, i64: 4, u8: 10, u16: 11, u32: 12, u64: 13, some: Some(17), none: None, a: [1, 2, 3], }; #[cfg(feature = "use_std")] { println!("Test value: {:#?}", v); } v } mod slice_tests { use super::*; #[test] #[cfg(feature = "use_nightly")] fn roundtrip() { let input = test_val(); let mut ser_buf = [0u8; max_serialize_buf_len::()]; let mut enc_buf = [0u8; max_encoded_len::()]; let len = super::encode_to_slice( &input, &mut ser_buf, &mut enc_buf ).unwrap(); let enc = &enc_buf[0..len]; let output = super::decode_from_slice(&enc, &mut ser_buf).unwrap(); assert_eq!(input, output); } #[test] #[should_panic] fn bad_ser_buf_len() { let mut ser_buf = [0u8; 1]; let mut enc = [0u8; 100]; super::encode_to_slice( &test_val(), &mut ser_buf, &mut enc ).unwrap(); } #[test] #[should_panic] fn bad_dest_len() { let mut ser_buf = [0u8; 100]; let mut enc = [0u8; 1]; super::encode_to_slice( &test_val(), &mut ser_buf, &mut enc ).unwrap(); } } mod len_tests { use super::*; #[test] fn serialize_buf_len() { assert_eq!(max_serialize_buf_len::(), 42); assert_eq!(max_serialize_buf_len::(), 3); assert_eq!(max_serialize_buf_len::(), 4); assert_eq!(max_serialize_buf_len::(), 6); assert_eq!(max_serialize_buf_len::(), 10); } #[test] fn encoded_len() { assert_eq!(max_encoded_len::(), 44); assert_eq!(max_encoded_len::(), 5); } } #[cfg(feature = "use_std")] mod rw_tests { use channel::Channel; use error::Error; use std::io::{Read, Write}; use super::*; #[test] fn one() { let (mut tx, mut rx) = pair(); let v = test_val(); tx.send(&v).unwrap(); let r = rx.recv().unwrap(); println!("r: {:#?}", r); assert_eq!(v, r); } #[test] fn empty_input() { let (mut _tx, mut rx) = pair(); match rx.recv() { Err(Error::EofBeforeFrame) => (), e @ _ => panic!("Bad value: {:?}", e) } } fn pair() -> (Sender, Test>, Receiver, Test>) { let c = Channel::new(); let tx = Sender::new(Box::new(c.writer()) as Box); let rx = Receiver::new(Box::new(c.reader()) as Box); (tx, rx) } } }