From 539637d78bcc1d1d9fe64bb4e1da4675a312a3e5 Mon Sep 17 00:00:00 2001 From: Ty Overby Date: Sun, 19 Mar 2017 20:10:35 -0700 Subject: [PATCH] remove refbox (#140) --- src/lib.rs | 1 - src/refbox.rs | 363 -------------------------------------------------- tests/test.rs | 44 +++--- 3 files changed, 15 insertions(+), 393 deletions(-) delete mode 100644 src/refbox.rs diff --git a/src/lib.rs b/src/lib.rs index efff3bc..5515581 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,6 @@ extern crate byteorder; extern crate num_traits; extern crate serde as serde_crate; -pub mod refbox; mod serde; pub mod endian_choice { diff --git a/src/refbox.rs b/src/refbox.rs deleted file mode 100644 index be663f9..0000000 --- a/src/refbox.rs +++ /dev/null @@ -1,363 +0,0 @@ -use std::boxed::Box; -use std::ops::Deref; - -use serde_crate as serde; - -/// A struct for encoding nested reference types. -/// -/// Encoding large objects by reference is really handy. For example, -/// `encode(&large_hashmap, ...)` encodes the large structure without having to -/// own the hashmap. However, it is impossible to serialize a reference if that -/// reference is inside of a struct. -/// -/// ```ignore rust -/// // Not possible, rustc can not decode the reference. -/// #[derive(RustcEncoding, RustcDecoding)] -/// struct Message<'a> { -/// big_map: &'a HashMap, -/// message_type: String, -/// } -/// ``` -/// -/// This is because on the decoding side, you can't create the Message struct -/// because it needs to have a reference to a HashMap, which is impossible because -/// during deserialization, all members need to be owned by the deserialized -/// object. -/// -/// This is where RefBox comes in. During serialization, it serializs a reference, -/// but during deserialization, it puts that sub-object into a box! -/// -/// ```ignore rust -/// // This works! -/// #[derive(RustcEncoding, RustcDecoding)] -/// struct Message<'a> { -/// big_map: RefBox<'a, HashMap>, -/// message_type: String -/// } -/// ``` -/// -/// Now we can write -/// -/// ```ignore rust -/// let my_map = HashMap::new(); -/// let my_msg = Message { -/// big_map: RefBox::new(&my_map), -/// message_type: "foo".to_string() -/// }; -/// -/// let encoded = encode(&my_msg, ...).unwrap(); -/// let decoded: Message<'static> = decode(&encoded[]).unwrap(); -/// ``` -/// -/// Notice that we managed to encode and decode a struct with a nested reference -/// and that the decoded message has the lifetime `'static` which shows us -/// that the message owns everything inside it completely. -/// -/// Please don't stick RefBox inside deep data structures. It is much better -/// suited in the outermost layer of whatever it is that you are encoding. -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] -pub struct RefBox<'a, T: 'a> { - inner: RefBoxInner<'a, T, Box> -} - -/// Like a RefBox, but encoding from a `str` and decoedes to a `String`. -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] -pub struct StrBox<'a> { - inner: RefBoxInner<'a, str, String> -} - -/// Like a RefBox, but encodes from a `[T]` and encodes to a `Vec`. -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] -pub struct SliceBox<'a, T: 'a> { - inner: RefBoxInner<'a, [T], Vec> -} - -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash)] -enum RefBoxInner<'a, A: 'a + ?Sized, B> { - Ref(&'a A), - Box(B) -} - -impl<'a, T> Clone for RefBoxInner<'a, T, Box> where T: Clone { - fn clone(&self) -> RefBoxInner<'a, T, Box> { - match *self { - RefBoxInner::Ref(reff) => RefBoxInner::Box(Box::new(reff.clone())), - RefBoxInner::Box(ref boxed) => RefBoxInner::Box(boxed.clone()) - } - } -} - -impl<'a> Clone for RefBoxInner<'a, str, String> { - fn clone(&self) -> RefBoxInner<'a, str, String> { - match *self { - RefBoxInner::Ref(reff) => RefBoxInner::Box(String::from(reff)), - RefBoxInner::Box(ref boxed) => RefBoxInner::Box(boxed.clone()) - } - } -} - -impl<'a, T> Clone for RefBoxInner<'a, [T], Vec> where T: Clone { - fn clone(&self) -> RefBoxInner<'a, [T], Vec> { - match *self { - RefBoxInner::Ref(reff) => RefBoxInner::Box(Vec::from(reff)), - RefBoxInner::Box(ref boxed) => RefBoxInner::Box(boxed.clone()) - } - } -} - -impl <'a, T> RefBox<'a, T> { - /// Creates a new RefBox that looks at a borrowed value. - pub fn new(v: &'a T) -> RefBox<'a, T> { - RefBox { - inner: RefBoxInner::Ref(v) - } - } -} - -impl RefBox<'static, T> { - /// Takes the value out of this refbox. - /// - /// Fails if this refbox was not created out of a deserialization. - /// - /// Unless you are doing some really weird things with static references, - /// this function will never fail. - pub fn take(self) -> Box { - match self.inner { - RefBoxInner::Box(b) => b, - _ => unreachable!() - } - } - - /// Tries to take the value out of this refbox. - pub fn try_take(self) -> Result, RefBox<'static, T>> { - match self.inner { - RefBoxInner::Box(b) => Ok(b), - o => Err(RefBox{ inner: o}) - } - } -} - -impl<'a, T> serde::Serialize for RefBox<'a, T> - where T: serde::Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer - { - serde::Serialize::serialize(&self.inner, serializer) - } -} - -impl<'a, T: serde::Deserialize> serde::Deserialize for RefBox<'a, T> { - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer - { - let inner = try!(serde::Deserialize::deserialize(deserializer)); - Ok(RefBox{ inner: inner }) - } -} - -impl<'a> StrBox<'a> { - /// Creates a new StrBox that looks at a borrowed value. - pub fn new(s: &'a str) -> StrBox<'a> { - StrBox { - inner: RefBoxInner::Ref(s) - } - } - - /// Extract a String from a StrBox. - pub fn into_string(self) -> String { - match self.inner { - RefBoxInner::Ref(s) => String::from(s), - RefBoxInner::Box(s) => s - } - } - - /// Convert to an Owned `SliceBox`. - pub fn to_owned(self) -> StrBox<'static> { - match self.inner { - RefBoxInner::Ref(s) => StrBox::boxed(String::from(s)), - RefBoxInner::Box(s) => StrBox::boxed(s) - } - } -} - -impl<'a> AsRef for StrBox<'a> { - fn as_ref(&self) -> &str { - match self.inner { - RefBoxInner::Ref(ref s) => s, - RefBoxInner::Box(ref s) => s - } - } -} - -impl StrBox<'static> { - /// Creates a new StrBox made from an allocated String. - pub fn boxed(s: String) -> StrBox<'static> { - StrBox { inner: RefBoxInner::Box(s) } - } - - /// Takes the value out of this refbox. - /// - /// Fails if this refbox was not created out of a deserialization. - /// - /// Unless you are doing some really weird things with static references, - /// this function will never fail. - pub fn take(self) -> String { - match self.inner { - RefBoxInner::Box(b) => b, - RefBoxInner::Ref(b) => String::from(b) - } - } - - /// Tries to take the value out of this refbox. - pub fn try_take(self) -> Result> { - match self.inner { - RefBoxInner::Box(b) => Ok(b), - o => Err(StrBox{ inner: o}) - } - } -} - - -impl<'a> serde::Serialize for StrBox<'a> { - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer - { - serde::Serialize::serialize(&self.inner, serializer) - } -} - -impl serde::Deserialize for StrBox<'static> { - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer - { - let inner = try!(serde::Deserialize::deserialize(deserializer)); - Ok(StrBox{ inner: inner }) - } -} - -// -// SliceBox -// - -impl <'a, T> SliceBox<'a, T> { - /// Creates a new RefBox that looks at a borrowed value. - pub fn new(v: &'a [T]) -> SliceBox<'a, T> { - SliceBox { - inner: RefBoxInner::Ref(v) - } - } - - /// Extract a `Vec` from a `SliceBox`. - pub fn into_vec(self) -> Vec where T: Clone { - match self.inner { - RefBoxInner::Ref(s) => s.to_vec(), - RefBoxInner::Box(s) => s - } - } - - /// Convert to an Owned `SliceBox`. - pub fn to_owned(self) -> SliceBox<'static, T> where T: Clone { - match self.inner { - RefBoxInner::Ref(s) => SliceBox::boxed(s.to_vec()), - RefBoxInner::Box(s) => SliceBox::boxed(s) - } - } -} - -impl SliceBox<'static, T> { - /// Creates a new SliceBox made from an allocated `Vec`. - pub fn boxed(s: Vec) -> SliceBox<'static, T> { - SliceBox { inner: RefBoxInner::Box(s) } - } - - /// Takes the value out of this refbox. - /// - /// Fails if this refbox was not created out of a deserialization. - /// - /// Unless you are doing some really weird things with static references, - /// this function will never fail. - pub fn take(self) -> Vec { - match self.inner { - RefBoxInner::Box(b) => b, - _ => unreachable!() - } - } - - /// Tries to take the value out of this refbox. - pub fn try_take(self) -> Result, SliceBox<'static, T>> { - match self.inner { - RefBoxInner::Box(b) => Ok(b), - o => Err(SliceBox{ inner: o}) - } - } -} - - -impl<'a, T> serde::Serialize for SliceBox<'a, T> - where T: serde::Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer - { - serde::Serialize::serialize(&self.inner, serializer) - } -} - -impl<'a, T: serde::Deserialize> serde::Deserialize for SliceBox<'a, T> { - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer - { - let inner = try!(serde::Deserialize::deserialize(deserializer)); - Ok(SliceBox{ inner: inner }) - } -} - - -impl<'a, A: ?Sized, B> serde::Serialize for RefBoxInner<'a, A, B> - where A: serde::Serialize, - B: serde::Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where S: serde::Serializer - { - match self { - &RefBoxInner::Ref(ref r) => serde::Serialize::serialize(r, serializer), - &RefBoxInner::Box(ref b) => serde::Serialize::serialize(b, serializer), - } - } -} - - -impl<'a, A: ?Sized, B> serde::Deserialize for RefBoxInner<'a, A, B> - where B: serde::Deserialize, -{ - fn deserialize(deserializer: D) -> Result - where D: serde::Deserializer - { - let deserialized = try!(serde::Deserialize::deserialize(deserializer)); - Ok(RefBoxInner::Box(deserialized)) - } -} - -impl <'a, T> Deref for RefBox<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - match &self.inner { - &RefBoxInner::Ref(ref t) => t, - &RefBoxInner::Box(ref b) => b.deref() - } - } -} - -impl <'a, T> Deref for SliceBox<'a, T> { - type Target = [T]; - - fn deref(&self) -> &[T] { - match &self.inner { - &RefBoxInner::Ref(ref t) => t, - &RefBoxInner::Box(ref b) => b.deref() - } - } -} diff --git a/tests/test.rs b/tests/test.rs index 9b31d3c..664e1b6 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -7,9 +7,7 @@ extern crate byteorder; use std::fmt::Debug; use std::collections::HashMap; -use std::ops::Deref; - -use bincode::refbox::{RefBox, StrBox, SliceBox}; +use std::borrow::Cow; use bincode::{Infinite, Bounded}; use bincode::{serialized_size, ErrorKind, Result}; @@ -22,17 +20,6 @@ use bincode::deserialize_from as deserialize_from_little; fn the_same(element: V) where V: serde::Serialize+serde::Deserialize+PartialEq+Debug+'static { - // Make sure that the bahavior isize correct when wrapping with a RefBox. - fn ref_box_correct(v: &V) -> bool - where V: serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static - { - let rf = RefBox::new(v); - let encoded = serialize_little(&rf, Infinite).unwrap(); - let decoded: RefBox<'static, V> = deserialize_little(&encoded[..]).unwrap(); - - decoded.take().deref() == v - } - let size = serialized_size(&element); { let encoded = serialize_little(&element, Infinite); @@ -42,7 +29,6 @@ fn the_same(element: V) assert_eq!(element, decoded); assert_eq!(size, encoded.len() as u64); - assert!(ref_box_correct(&element)); } { @@ -53,7 +39,6 @@ fn the_same(element: V) assert_eq!(element, decoded); assert_eq!(size, encoded.len() as u64); - assert!(ref_box_correct(&element)); } } @@ -304,7 +289,7 @@ fn encode_box() { } #[test] -fn test_refbox_serialize() { +fn test_cow_serialize() { let large_object = vec![1u32,2,3,4,5,6]; let mut large_map = HashMap::new(); large_map.insert(1, 2); @@ -312,28 +297,28 @@ fn test_refbox_serialize() { #[derive(Serialize, Deserialize, Debug)] enum Message<'a> { - M1(RefBox<'a, Vec>), - M2(RefBox<'a, HashMap>) + M1(Cow<'a, Vec>), + M2(Cow<'a, HashMap>) } // Test 1 { - let serialized = serialize_little(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap(); + let serialized = serialize_little(&Message::M1(Cow::Borrowed(&large_object)), Infinite).unwrap(); let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap(); match deserialized { - Message::M1(b) => assert!(b.take().deref() == &large_object), + Message::M1(b) => assert!(&b.into_owned() == &large_object), _ => assert!(false) } } // Test 2 { - let serialized = serialize_little(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap(); + let serialized = serialize_little(&Message::M2(Cow::Borrowed(&large_map)), Infinite).unwrap(); let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap(); match deserialized { - Message::M2(b) => assert!(b.take().deref() == &large_map), + Message::M2(b) => assert!(&b.into_owned() == &large_map), _ => assert!(false) } } @@ -342,22 +327,23 @@ fn test_refbox_serialize() { #[test] fn test_strbox_serialize() { let strx: &'static str = "hello world"; - let serialized = serialize_little(&StrBox::new(strx), Infinite).unwrap(); - let deserialized: StrBox<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap(); - let stringx: String = deserialized.take(); + let serialized = serialize_little(&Cow::Borrowed(strx), Infinite).unwrap(); + let deserialized: Cow<'static, String> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap(); + let stringx: String = deserialized.into_owned(); assert!(strx == &stringx[..]); } #[test] fn test_slicebox_serialize() { let slice = [1u32, 2, 3 ,4, 5]; - let serialized = serialize_little(&SliceBox::new(&slice), Infinite).unwrap(); - let deserialized: SliceBox<'static, u32> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap(); + let serialized = serialize_little(&Cow::Borrowed(&slice[..]), Infinite).unwrap(); + println!("{:?}", serialized); + let deserialized: Cow<'static, Vec> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap(); { let sb: &[u32] = &deserialized; assert!(slice == sb); } - let vecx: Vec = deserialized.take(); + let vecx: Vec = deserialized.into_owned(); assert!(slice == &vecx[..]); }