diff --git a/Cargo.toml b/Cargo.toml index 2116d37..b99179c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_traitobject" -version = "0.1.7" +version = "0.1.8" license = "MIT OR Apache-2.0" authors = ["Alec Mocatta "] categories = ["development-tools","encoding","rust-patterns","network-programming"] @@ -12,7 +12,7 @@ This library enables the serialization and deserialization of trait objects such """ repository = "https://github.com/alecmocatta/serde_traitobject" homepage = "https://github.com/alecmocatta/serde_traitobject" -documentation = "https://docs.rs/serde_traitobject/0.1.7" +documentation = "https://docs.rs/serde_traitobject/0.1.8" readme = "README.md" edition = "2018" diff --git a/README.md b/README.md index c641a24..7e014fb 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![MIT / Apache 2.0 licensed](https://img.shields.io/crates/l/serde_traitobject.svg?maxAge=2592000)](#License) [![Build Status](https://dev.azure.com/alecmocatta/serde_traitobject/_apis/build/status/tests?branchName=master)](https://dev.azure.com/alecmocatta/serde_traitobject/_build/latest?branchName=master) -[Docs](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/) +[Docs](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/) **Serializable and deserializable trait objects.** @@ -12,7 +12,7 @@ This library enables the serialization and deserialization of trait objects so t For example, if you have multiple forks of a process, or the same binary running on each of a cluster of machines, this library lets you send trait objects between them. -Any trait can be made (de)serializable when made into a trait object by adding this crate's [Serialize](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Deserialize.html) traits as supertraits: +Any trait can be made (de)serializable when made into a trait object by adding this crate's [Serialize](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Deserialize.html) traits as supertraits: ```rust trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { @@ -28,12 +28,12 @@ struct Message(#[serde(with = "serde_traitobject")] Box); And that's it! The two traits are automatically implemented for all `T: serde::Serialize` and all `T: serde::de::DeserializeOwned`, so as long as all implementors of your trait are themselves serializable then you're good to go. There are two ways to (de)serialize your trait object: - * Apply the `#[serde(with = "serde_traitobject")]` [field attribute](https://serde.rs/attributes.html), which instructs serde to use this crate's [serialize](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/fn.deserialize.html) functions; - * The [Box](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/struct.Arc.html) structs, which are simple wrappers around their stdlib counterparts that automatically handle (de)serialization without needing the above annotation; + * Apply the `#[serde(with = "serde_traitobject")]` [field attribute](https://serde.rs/attributes.html), which instructs serde to use this crate's [serialize](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/fn.deserialize.html) functions; + * The [Box](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/struct.Arc.html) structs, which are simple wrappers around their stdlib counterparts that automatically handle (de)serialization without needing the above annotation; Additionally, there are several convenience traits implemented that extend their stdlib counterparts: - * [Any](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.FnOnce.html) + * [Any](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.FnOnce.html) These are automatically implemented on all implementors of their stdlib counterparts that also implement `serde::Serialize` and `serde::de::DeserializeOwned`. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c35ccad..e92d94c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,7 +14,7 @@ jobs: endpoint: alecmocatta default: rust_toolchain: nightly - rust_lint_toolchain: nightly-2019-08-15 + rust_lint_toolchain: nightly-2019-10-15 rust_flags: '' rust_features: '' rust_target_check: '' diff --git a/src/lib.rs b/src/lib.rs index 83f6503..a95196c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,6 @@ //! //! ``` //! # use serde_derive::{Serialize, Deserialize}; -//! # fn main() { //! trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { //! fn my_method(&self); //! } @@ -19,7 +18,6 @@ //! struct Message(#[serde(with = "serde_traitobject")] Box); //! //! // Woohoo, `Message` is now serializable! -//! # } //! ``` //! //! And that's it! The two traits are automatically implemented for all `T: serde::Serialize` and all `T: serde::de::DeserializeOwned`, so as long as all implementors of your trait are themselves serializable then you're good to go. @@ -36,7 +34,6 @@ //! //! ``` //! # use serde_derive::{Serialize, Deserialize}; -//! # fn main() { //! use std::any::Any; //! use serde_traitobject as s; //! @@ -61,7 +58,6 @@ //! println!("{:?}", downcast); //! # assert_eq!(format!("{:?}", downcast), "MyStruct { foo: \"abc\", bar: 123 }"); //! // MyStruct { foo: "abc", bar: 123 } -//! # } //! ``` //! //! # Security @@ -98,8 +94,9 @@ //! //! This crate currently requires Rust nightly. -#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.1.7")] +#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.1.8")] #![feature( + arbitrary_self_types, coerce_unsized, core_intrinsics, fn_traits, @@ -138,18 +135,15 @@ pub use convenience::*; /// ``` /// use serde_derive::{Serialize, Deserialize}; /// -/// # fn main() { /// trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { /// fn my_method(&self); /// } -/// # } /// ``` /// /// Now your trait object is serializable! /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// # -/// # fn main() { /// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { /// # fn my_method(&self); /// # } @@ -157,13 +151,11 @@ pub use convenience::*; /// struct Message(#[serde(with = "serde_traitobject")] Box); /// /// // Woohoo, `Message` is now serializable! -/// # } /// ``` /// /// Any implementers of `MyTrait` would now have to themselves implement `serde::Serialize` and `serde::de::DeserializeOwned`. This would typically be through `serde_derive`, like: /// ``` /// # use serde_derive::{Serialize, Deserialize}; -/// # fn main() { /// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { /// # fn my_method(&self); /// # } @@ -179,7 +171,6 @@ pub use convenience::*; /// println!("foo: {}", self.foo); /// } /// } -/// # } /// ``` pub trait Serialize: serialize::Sealed {} impl Serialize for T {} @@ -192,18 +183,15 @@ impl Serialize for T {} /// ``` /// use serde_derive::{Serialize, Deserialize}; /// -/// # fn main() { /// trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { /// fn my_method(&self); /// } -/// # } /// ``` /// /// Now your trait object is serializable! /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// # -/// # fn main() { /// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { /// # fn my_method(&self); /// # } @@ -211,13 +199,11 @@ impl Serialize for T {} /// struct Message(#[serde(with = "serde_traitobject")] Box); /// /// // Woohoo, `Message` is now serializable! -/// # } /// ``` /// /// Any implementers of `MyTrait` would now have to themselves implement `serde::Serialize` and `serde::de::DeserializeOwned`. This would typically be through `serde_derive`, like: /// ``` /// # use serde_derive::{Serialize, Deserialize}; -/// # fn main() { /// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { /// # fn my_method(&self); /// # } @@ -233,7 +219,6 @@ impl Serialize for T {} /// println!("foo: {}", self.foo); /// } /// } -/// # } /// ``` pub trait Deserialize: deserialize::Sealed {} impl Deserialize for T {} @@ -283,7 +268,7 @@ mod deserialize { /// Unsafe as it `ptr::write`s into `&mut self`, assuming it to be uninitialized #[inline(always)] unsafe fn deserialize_erased( - &mut self, deserializer: &mut dyn erased_serde::Deserializer, + self: *mut Self, deserializer: &mut dyn erased_serde::Deserializer, ) -> Result<(), erased_serde::Error> { let _ = deserializer; unreachable!() @@ -308,7 +293,7 @@ mod deserialize { impl Sealed for T { #[inline(always)] unsafe fn deserialize_erased( - &mut self, deserializer: &mut dyn erased_serde::Deserializer, + self: *mut Self, deserializer: &mut dyn erased_serde::Deserializer, ) -> Result<(), erased_serde::Error> { erased_serde::deserialize(deserializer).map(|x| ptr::write(self, x)) } @@ -453,7 +438,7 @@ impl DeserializerTrait for Deserializer }); let t1: u64 = match seq.next_element()? { Some(value) => value, - None => return Err(serde::de::Error::invalid_length(1, &self)), + None => return Err(serde::de::Error::invalid_length(1, &self)), // TODO: don't leak uninitialized box }; assert_eq!(t1, object.type_id(), "Deserializing the trait object \"{}\" failed in a way that should never happen. Please file an issue! https://github.com/alecmocatta/serde_traitobject/issues/new", type_name::()); let t2: boxed::Box = match seq @@ -477,11 +462,16 @@ impl<'de, T: Deserialize + ?Sized> serde::de::DeserializeSeed<'de> for Deseriali D: serde::de::Deserializer<'de>, { let mut x = self.0; - unsafe { - (&mut *x).deserialize_erased(&mut erased_serde::Deserializer::erase(deserializer)) + let x_ptr: *mut T = &mut *x; + match unsafe { + x_ptr.deserialize_erased(&mut erased_serde::Deserializer::erase(deserializer)) + } { + Ok(()) => Ok(x), + Err(err) => { + mem::forget(x); // TODO: don't leak uninitialized box + Err(serde::de::Error::custom(err)) + } } - .map(|()| x) - .map_err(serde::de::Error::custom) } } @@ -491,26 +481,22 @@ impl<'de, T: Deserialize + ?Sized> serde::de::DeserializeSeed<'de> for Deseriali /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// -/// # fn main() { /// #[derive(Serialize, Deserialize)] /// struct MyStruct { /// #[serde(with = "serde_traitobject")] /// field: Box, /// } -/// # } /// ``` /// /// Or, alternatively, if only Serialize is desired: /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// -/// # fn main() { /// #[derive(Serialize)] /// struct MyStruct { /// #[serde(serialize_with = "serde_traitobject::serialize")] /// field: Box, /// } -/// # } /// ``` pub fn serialize + ?Sized, S>( t: &B, serializer: S, @@ -527,26 +513,22 @@ where /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// -/// # fn main() { /// #[derive(Serialize, Deserialize)] /// struct MyStruct { /// #[serde(with = "serde_traitobject")] /// field: Box, /// } -/// # } /// ``` /// /// Or, alternatively, if only Deserialize is desired: /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// -/// # fn main() { /// #[derive(Deserialize)] /// struct MyStruct { /// #[serde(deserialize_with = "serde_traitobject::deserialize")] /// field: Box, /// } -/// # } /// ``` pub fn deserialize<'de, T: Deserialize + ?Sized + 'static, B, D>( deserializer: D, diff --git a/tests/test.rs b/tests/test.rs index 75bd89e..8338fd9 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -66,6 +66,7 @@ impl Hello for u8 { } } +#[allow(clippy::too_many_lines)] fn main() { let test = |Abc { a,