From d2be0153cb3932e63ddf533b3ff11361cd90cd62 Mon Sep 17 00:00:00 2001 From: alecmocatta Date: Tue, 14 Jul 2020 14:10:57 +0100 Subject: [PATCH 1/2] convenience traits for serde_closure::traits::* --- Cargo.toml | 5 +- azure-pipelines.yml | 4 +- src/convenience.rs | 186 ++++++++++++++++++++++++++++++++++++++++++-- tests/test.rs | 3 - 4 files changed, 186 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ee4c0e3..e47cae1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,12 +25,13 @@ serde = "1.0" erased-serde = "0.3" metatype = "0.2" relative = "0.2" +serde_closure = { version = "0.3", optional = true } [dev-dependencies] +bincode = "1.0" +serde_closure = "0.3" serde_derive = "1.0" serde_json = "1.0" -bincode = "1.0" -serde_closure = "0.2.2" wasm-bindgen-test = "0.3" [[test]] diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 324f8a8..d1d1e51 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -14,8 +14,8 @@ jobs: endpoint: alecmocatta default: rust_toolchain: nightly - rust_lint_toolchain: nightly-2020-06-25 - rust_flags: '' + rust_lint_toolchain: nightly-2020-07-12 + rust_flags: ';serde_closure' rust_features: '' rust_target_check: '' rust_target_build: '' diff --git a/src/convenience.rs b/src/convenience.rs index d779038..096e420 100644 --- a/src/convenience.rs +++ b/src/convenience.rs @@ -25,7 +25,6 @@ impl Box { self.0.into_any() } } -#[allow(clippy::use_self)] impl Box { /// Convert into a `std::boxed::Box`. pub fn into_any_send(self) -> boxed::Box { @@ -34,7 +33,6 @@ impl Box { } } } -#[allow(clippy::use_self)] impl Box { /// Convert into a `std::boxed::Box`. pub fn into_any_sync(self) -> boxed::Box { @@ -43,7 +41,6 @@ impl Box { } } } -#[allow(clippy::use_self)] impl Box { /// Convert into a `std::boxed::Box`. pub fn into_any_send_sync(self) -> boxed::Box { @@ -504,13 +501,11 @@ impl<'a> AsRef for dyn Error + Send + 'a { } } -#[allow(clippy::use_self)] impl<'a, E: error::Error + Serialize + Deserialize + 'a> From for Box { fn from(err: E) -> Self { Box::new(err) } } -#[allow(clippy::use_self)] impl<'a, E: error::Error + Serialize + Deserialize + 'a> From for boxed::Box { fn from(err: E) -> Self { boxed::Box::new(err) @@ -858,3 +853,184 @@ impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> .map(|x| x.0) } } + +/// Convenience traits implemented on all (de)serializable implementors of [`serde_closure::traits::*`](serde_closure::traits). +#[cfg(feature = "serde_closure")] +pub mod sc { + use super::{serialize, Box, Deserialize, Serialize}; + use serde_closure::traits as sc; + use std::boxed; + + /// A convenience trait implemented on all (de)serializable implementors of [`serde_closure::traits::FnOnce`]. + /// + /// It can be made into a trait object which is then (de)serializable. + pub trait FnOnce: sc::FnOnceBox + Serialize + Deserialize {} + impl FnOnce for T where T: sc::FnOnceBox + Serialize + Deserialize {} + + impl<'a, Args, Output> AsRef for dyn FnOnce + 'a { + fn as_ref(&self) -> &Self { + self + } + } + impl<'a, Args, Output> AsRef for dyn FnOnce + Send + 'a { + fn as_ref(&self) -> &Self { + self + } + } + + impl serde::ser::Serialize for dyn FnOnce { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serialize(self, serializer) + } + } + impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> + for boxed::Box + 'static> + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + + 'static>>::deserialize(deserializer) + .map(|x| x.0) + } + } + impl serde::ser::Serialize + for dyn FnOnce + Send + { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serialize(self, serializer) + } + } + impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> + for boxed::Box + Send + 'static> + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + + Send + 'static>>::deserialize(deserializer) + .map(|x| x.0) + } + } + + /// A convenience trait implemented on all (de)serializable implementors of [`serde_closure::traits::FnMut`]. + /// + /// It can be made into a trait object which is then (de)serializable. + pub trait FnMut: sc::FnMut + Serialize + Deserialize {} + impl FnMut for T where T: sc::FnMut + Serialize + Deserialize {} + + impl<'a, Args, Output> AsRef for dyn FnMut + 'a { + fn as_ref(&self) -> &Self { + self + } + } + impl<'a, Args, Output> AsRef for dyn FnMut + Send + 'a { + fn as_ref(&self) -> &Self { + self + } + } + + impl serde::ser::Serialize for dyn FnMut { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serialize(self, serializer) + } + } + impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> + for boxed::Box + 'static> + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + + 'static>>::deserialize(deserializer) + .map(|x| x.0) + } + } + impl serde::ser::Serialize + for dyn FnMut + Send + { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serialize(self, serializer) + } + } + impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> + for boxed::Box + Send + 'static> + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + + Send + 'static>>::deserialize(deserializer) + .map(|x| x.0) + } + } + + /// A convenience trait implemented on all (de)serializable implementors of [`serde_closure::traits::Fn`]. + /// + /// It can be made into a trait object which is then (de)serializable. + pub trait Fn: sc::Fn + Serialize + Deserialize {} + impl Fn for T where T: sc::Fn + Serialize + Deserialize {} + + impl<'a, Args, Output> AsRef for dyn Fn + 'a { + fn as_ref(&self) -> &Self { + self + } + } + impl<'a, Args, Output> AsRef for dyn Fn + Send + 'a { + fn as_ref(&self) -> &Self { + self + } + } + + impl serde::ser::Serialize for dyn Fn { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serialize(self, serializer) + } + } + impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> + for boxed::Box + 'static> + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + + 'static>>::deserialize(deserializer).map(|x| x.0) + } + } + impl serde::ser::Serialize + for dyn Fn + Send + { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serialize(self, serializer) + } + } + impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de> + for boxed::Box + Send + 'static> + { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + + Send + 'static>>::deserialize(deserializer) + .map(|x| x.0) + } + } +} diff --git a/tests/test.rs b/tests/test.rs index 15038c6..4625b96 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -56,19 +56,16 @@ trait Hello { trait HelloSerialize: Hello + Serialize + Deserialize {} impl HelloSerialize for T where T: Hello + Serialize + Deserialize {} -#[allow(clippy::use_self)] impl Hello for u32 { fn hi(&self) -> String { format!("hi u32! {:?}", self) } } -#[allow(clippy::use_self)] impl Hello for u16 { fn hi(&self) -> String { format!("hi u16! {:?}", self) } } -#[allow(clippy::use_self)] impl Hello for u8 { fn hi(&self) -> String { format!("hi u8! {:?}", self) From 57f31364ddf5df1cadb0ef7322e12333e2f8f163 Mon Sep 17 00:00:00 2001 From: alecmocatta Date: Tue, 14 Jul 2020 14:39:21 +0100 Subject: [PATCH 2/2] v0.2.7 --- Cargo.toml | 4 ++-- README.md | 10 +++++----- azure-pipelines.yml | 4 ++-- src/lib.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e47cae1..d659c19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_traitobject" -version = "0.2.6" +version = "0.2.7" 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.2.6" +documentation = "https://docs.rs/serde_traitobject" readme = "README.md" edition = "2018" diff --git a/README.md b/README.md index b89b943..2082e0b 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?definitionId=9) -[📖 Docs](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/) | [💬 Chat](https://constellation.zulipchat.com/#narrow/stream/213236-subprojects) +[📖 Docs](https://docs.rs/serde_traitobject) | [💬 Chat](https://constellation.zulipchat.com/#narrow/stream/213236-subprojects) **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.2.6/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.2.6/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.2/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.Deserialize.html) traits as supertraits: ```rust trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize { @@ -31,12 +31,12 @@ struct Message { 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.2.6/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/fn.deserialize.html) functions; - * The [Box](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.2.6/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.2/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.2/serde_traitobject/fn.deserialize.html) functions; + * The [Box](https://docs.rs/serde_traitobject/0.2/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.2/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.2/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.2.6/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.FnOnce.html) + * [Any](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.2/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.2/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 d1d1e51..8efbc2b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,8 +15,8 @@ jobs: default: rust_toolchain: nightly rust_lint_toolchain: nightly-2020-07-12 - rust_flags: ';serde_closure' - rust_features: '' + rust_flags: '' + rust_features: ';serde_closure' rust_target_check: '' rust_target_build: '' rust_target_run: '' diff --git a/src/lib.rs b/src/lib.rs index b9fdc5b..69583da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,7 +99,7 @@ //! //! This crate currently requires Rust nightly. -#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.2.6")] +#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.2.7")] #![feature( arbitrary_self_types, coerce_unsized,