1
Fork 0

Improved ergonomics of config builder, more tests.

Closes #26, #24.
This commit is contained in:
Alex Helfet 2017-12-31 15:47:19 +00:00
parent dd17f1f65d
commit 22445c2144
4 changed files with 67 additions and 37 deletions

View file

@ -48,7 +48,7 @@ fn try() -> Result<()> {
let mut r = framed::bytes::Config::default() let mut r = framed::bytes::Config::default()
.typed::<UserType>() .typed::<UserType>()
.into_receiver(stdin()); .to_receiver(stdin());
let mut csvw: Option<csv::Writer<_>> = let mut csvw: Option<csv::Writer<_>> =
match out_fmt { match out_fmt {

View file

@ -14,19 +14,19 @@
//! # use framed::bytes::*; //! # use framed::bytes::*;
//! # use std::io::Cursor; //! # use std::io::Cursor;
//! # //! #
//! let config = Config::default(); //! let mut config = Config::default();
//! //!
//! let payload = [1, 2, 3]; //! let payload = [1, 2, 3];
//! //!
//! let mut encoded = vec![]; //! let mut encoded = vec![];
//! { //! {
//! let mut sender = config.clone().into_sender(&mut encoded); //! let mut sender = config.clone().to_sender(&mut encoded);
//! sender.send(&payload).expect("send ok"); //! sender.send(&payload).expect("send ok");
//! } //! }
//! //!
//! // `encoded` now contains the encoded frame. //! // `encoded` now contains the encoded frame.
//! //!
//! let mut receiver = config.clone().into_receiver(Cursor::new(encoded)); //! let mut receiver = config.clone().to_receiver(Cursor::new(encoded));
//! let decoded = receiver.recv().expect("recv ok"); //! let decoded = receiver.recv().expect("recv ok");
//! //!
//! assert_eq!(payload, *decoded); //! assert_eq!(payload, *decoded);
@ -42,7 +42,7 @@
//! # use framed::*; //! # use framed::*;
//! # use framed::bytes::*; //! # use framed::bytes::*;
//! # //! #
//! let mut codec = Config::default().into_codec(); //! let mut codec = Config::default().to_codec();
//! //!
//! // In a no_std crate without dynamic memory allocation we would typically //! // In a no_std crate without dynamic memory allocation we would typically
//! // know the maximum payload length, which we can use for payload buffers. //! // know the maximum payload length, which we can use for payload buffers.
@ -98,7 +98,7 @@ pub use ::checksum::Checksum;
/// specific configuration. /// specific configuration.
/// ///
/// Construct an instance from a `Config` instance with the /// Construct an instance from a `Config` instance with the
/// `Config::into_codec` method. /// `Config::to_codec` method.
pub struct Codec { pub struct Codec {
config: Config config: Config
} }
@ -114,33 +114,33 @@ pub struct Config {
impl Config { impl Config {
/// Construct a `Codec` instance with this configuration. /// Construct a `Codec` instance with this configuration.
pub fn into_codec(self) -> Codec { pub fn to_codec(&mut self) -> Codec {
Codec { Codec {
config: self, config: self.clone(),
} }
} }
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
/// Construct a `Receiver` instance with this configuration. /// Construct a `Receiver` instance with this configuration.
pub fn into_receiver<R: Read>(self, r: R) -> Receiver<R> { pub fn to_receiver<R: Read>(&mut self, r: R) -> Receiver<R> {
Receiver::<R> { Receiver::<R> {
codec: self.into_codec(), codec: self.to_codec(),
r: r, r: r,
} }
} }
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
/// Construct a `Sender` instance with this configuration. /// Construct a `Sender` instance with this configuration.
pub fn into_sender<W: Write>(self, w: W) -> Sender<W> { pub fn to_sender<W: Write>(&mut self, w: W) -> Sender<W> {
Sender::<W> { Sender::<W> {
codec: self.into_codec(), codec: self.to_codec(),
w: w, w: w,
} }
} }
/// Construct a `framed::typed::Config` instance to encode and decode a /// Construct a `framed::typed::Config` instance to encode and decode a
/// serializable type `T` with this byte encoding configuration. /// serializable type `T` with this byte encoding configuration.
pub fn typed<T: DeserializeOwned + Serialize>(self) -> typed::Config<T> { pub fn typed<T: DeserializeOwned + Serialize>(&mut self) -> typed::Config<T> {
typed::Config::<T>::new(self) typed::Config::<T>::new(self)
} }
@ -528,7 +528,7 @@ mod tests {
} }
fn codec() -> Codec { fn codec() -> Codec {
Config::default().into_codec() Config::default().to_codec()
} }
// A test payload. // A test payload.
@ -710,9 +710,39 @@ mod tests {
let decoded = c.decode_from_reader::<Cursor<&[u8]>>(&mut reader).unwrap(); let decoded = c.decode_from_reader::<Cursor<&[u8]>>(&mut reader).unwrap();
assert_eq!(&*decoded, &PAYLOAD); assert_eq!(&*decoded, &PAYLOAD);
} }
#[test]
#[cfg(feature = "use_std")]
fn roundtrip_default_config() {
roundtrip_case(&mut Config::default()
.to_codec(),
&PAYLOAD)
} }
// TODO: Some more roundtrip cases. #[test]
#[cfg(feature = "use_std")]
fn roundtrip_no_checksum() {
roundtrip_case(&mut Config::default()
.set_checksum(Checksum::None)
.to_codec(),
&PAYLOAD)
}
#[test]
#[cfg(feature = "use_std")]
fn roundtrip_empty_payload() {
roundtrip_case(&mut Config::default()
.to_codec(),
&[])
}
#[cfg(feature = "use_std")]
fn roundtrip_case(c: &mut Codec, payload: &Payload) {
let encoded = c.encode_to_box(payload).unwrap();
let decoded = c.decode_to_box(&*encoded).unwrap();
assert_eq!(&*decoded, payload);
}
}
#[cfg(all(test, feature = "use_std"))] #[cfg(all(test, feature = "use_std"))]
mod rw_tests { mod rw_tests {
@ -778,7 +808,7 @@ mod rw_tests {
#[test] #[test]
fn partial_input() { fn partial_input() {
let chan = Channel::new(); let chan = Channel::new();
let mut rx = config().into_receiver(chan.reader()); let mut rx = config().to_receiver(chan.reader());
let mut tx_raw = chan.writer(); let mut tx_raw = chan.writer();
tx_raw.write(&[0x01]).unwrap(); tx_raw.write(&[0x01]).unwrap();
match rx.recv() { match rx.recv() {
@ -794,8 +824,8 @@ mod rw_tests {
fn pair() -> (Sender<Box<Write>>, Receiver<Box<Read>>) { fn pair() -> (Sender<Box<Write>>, Receiver<Box<Read>>) {
let chan = Channel::new(); let chan = Channel::new();
let c = config(); let c = config();
let tx = c.clone().into_sender(Box::new(chan.writer()) as Box<Write>); let tx = c.clone().to_sender(Box::new(chan.writer()) as Box<Write>);
let rx = c.clone().into_receiver(Box::new(chan.reader()) as Box<Read>); let rx = c.clone().to_receiver(Box::new(chan.reader()) as Box<Read>);
(tx, rx) (tx, rx)
} }
} }

View file

@ -34,17 +34,17 @@
//! } //! }
//! //!
//! let payload = Test { a: 1, b: 2 }; //! let payload = Test { a: 1, b: 2 };
//! let config = framed::bytes::Config::default().typed::<Test>(); //! let mut config = framed::bytes::Config::default().typed::<Test>();
//! //!
//! let mut encoded = vec![]; //! let mut encoded = vec![];
//! { //! {
//! let mut sender = config.clone().into_sender(&mut encoded); //! let mut sender = config.clone().to_sender(&mut encoded);
//! sender.send(&payload).expect("send ok"); //! sender.send(&payload).expect("send ok");
//! } //! }
//! //!
//! // `encoded` now contains the encoded value. //! // `encoded` now contains the encoded value.
//! //!
//! let mut receiver = config.clone().into_receiver(Cursor::new(encoded)); //! let mut receiver = config.clone().to_receiver(Cursor::new(encoded));
//! let decoded = receiver.recv().expect("recv ok"); //! let decoded = receiver.recv().expect("recv ok");
//! //!
//! assert_eq!(payload, decoded); //! assert_eq!(payload, decoded);
@ -73,9 +73,9 @@
//! # } //! # }
//! # //! #
//! # let payload = Test { a: 1, b: 2 }; //! # let payload = Test { a: 1, b: 2 };
//! # let config = bytes::Config::default().typed::<Test>(); //! # let mut config = bytes::Config::default().typed::<Test>();
//! # //! #
//! let mut codec = config.into_codec(); //! let mut codec = config.to_codec();
//! let mut ser_buf = [0u8; max_serialize_buf_len::<Test>()]; //! let mut ser_buf = [0u8; max_serialize_buf_len::<Test>()];
//! let mut encoded_buf = [0u8; max_encoded_len::<Test>()]; //! let mut encoded_buf = [0u8; max_encoded_len::<Test>()];
//! let encoded_len = codec.encode_to_slice( //! let encoded_len = codec.encode_to_slice(
@ -110,7 +110,7 @@ use std::io::{Read, Write};
/// with a specific configuration. /// with a specific configuration.
/// ///
/// Construct an instance from a `Config` instance with the /// Construct an instance from a `Config` instance with the
/// `Config::into_codec` method. /// `Config::to_codec` method.
pub struct Codec<T: DeserializeOwned + Serialize> { pub struct Codec<T: DeserializeOwned + Serialize> {
bytes_codec: bytes::Codec, bytes_codec: bytes::Codec,
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
@ -135,35 +135,35 @@ impl<T: DeserializeOwned + Serialize> Clone for Config<T> {
} }
impl<T: DeserializeOwned + Serialize> Config<T> { impl<T: DeserializeOwned + Serialize> Config<T> {
pub(crate) fn new(bytes_config: bytes::Config) -> Config<T> { pub(crate) fn new(bytes_config: &bytes::Config) -> Config<T> {
Config::<T> { Config::<T> {
bytes_config: bytes_config, bytes_config: bytes_config.clone(),
_phantom: PhantomData::<T>::default(), _phantom: PhantomData::<T>::default(),
} }
} }
/// Construct a `Codec` instance with this configuration. /// Construct a `Codec` instance with this configuration.
pub fn into_codec(self) -> Codec<T> { pub fn to_codec(&mut self) -> Codec<T> {
Codec::<T> { Codec::<T> {
bytes_codec: self.bytes_config.into_codec(), bytes_codec: self.bytes_config.to_codec(),
_phantom: PhantomData::<T>::default(), _phantom: PhantomData::<T>::default(),
} }
} }
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
/// Construct a `Receiver` instance with this configuration. /// Construct a `Receiver` instance with this configuration.
pub fn into_receiver<R: Read>(self, r: R) -> Receiver<R, T> { pub fn to_receiver<R: Read>(&mut self, r: R) -> Receiver<R, T> {
Receiver::<R, T> { Receiver::<R, T> {
codec: self.into_codec(), codec: self.to_codec(),
r: r, r: r,
} }
} }
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
/// Construct a `Sender` instance with this configuration. /// Construct a `Sender` instance with this configuration.
pub fn into_sender<W: Write>(self, w: W) -> Sender<W, T> { pub fn to_sender<W: Write>(&mut self, w: W) -> Sender<W, T> {
Sender::<W, T> { Sender::<W, T> {
codec: self.into_codec(), codec: self.to_codec(),
w: w, w: w,
} }
} }
@ -400,7 +400,7 @@ mod tests {
} }
fn codec() -> Codec<Test> { fn codec() -> Codec<Test> {
bytes::Config::default().typed::<Test>().into_codec() bytes::Config::default().typed::<Test>().to_codec()
} }
mod slice_tests { mod slice_tests {
@ -492,9 +492,9 @@ mod tests {
let chan = Channel::new(); let chan = Channel::new();
let conf = bytes::Config::default().typed::<Test>(); let conf = bytes::Config::default().typed::<Test>();
let tx = conf.clone() let tx = conf.clone()
.into_sender(Box::new(chan.writer()) as Box<Write>); .to_sender(Box::new(chan.writer()) as Box<Write>);
let rx = conf.clone() let rx = conf.clone()
.into_receiver(Box::new(chan.reader()) as Box<Read>); .to_receiver(Box::new(chan.reader()) as Box<Read>);
(tx, rx) (tx, rx)
} }
} }

View file

@ -15,6 +15,6 @@ fn main() {
eprintln!("test_type/main.rs: Sending sample value: {:#?}", t); eprintln!("test_type/main.rs: Sending sample value: {:#?}", t);
let mut s = framed::bytes::Config::default() let mut s = framed::bytes::Config::default()
.typed::<Test>() .typed::<Test>()
.into_sender(stdout()); .to_sender(stdout());
s.send(&t).unwrap(); s.send(&t).unwrap();
} }