Skip to content

Commit

Permalink
Merge pull request #28 from alecmocatta/fix-nightly
Browse files Browse the repository at this point in the history
Fix on latest nightly
  • Loading branch information
alecmocatta authored Jun 25, 2020
2 parents aa553ab + 9dec91f commit 3a739ec
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 132 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "serde_traitobject"
version = "0.2.5"
version = "0.2.6"
license = "MIT OR Apache-2.0"
authors = ["Alec Mocatta <alec@mocatta.net>"]
categories = ["development-tools","encoding","rust-patterns","network-programming"]
Expand All @@ -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.5"
documentation = "https://docs.rs/serde_traitobject/0.2.6"
readme = "README.md"
edition = "2018"

Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
[![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.5/serde_traitobject/) | [💬 Chat](https://constellation.zulipchat.com/#narrow/stream/213236-subprojects)
[📖 Docs](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/) | [💬 Chat](https://constellation.zulipchat.com/#narrow/stream/213236-subprojects)

**Serializable and deserializable trait objects.**

This library enables the serialization and deserialization of trait objects so they can be sent between other processes running the same binary.

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.5/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.2.5/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.6/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.2.6/serde_traitobject/trait.Deserialize.html) traits as supertraits:

```rust
trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
Expand All @@ -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.5/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/fn.deserialize.html) functions;
* The [Box](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.2.5/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.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;

Additionally, there are several convenience traits implemented that extend their stdlib counterparts:

* [Any](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/trait.FnOnce.html)
* [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)

These are automatically implemented on all implementors of their stdlib counterparts that also implement `serde::Serialize` and `serde::de::DeserializeOwned`.

Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
endpoint: alecmocatta
default:
rust_toolchain: nightly
rust_lint_toolchain: nightly-2020-06-10
rust_lint_toolchain: nightly-2020-06-25
rust_flags: ''
rust_features: ''
rust_target_check: ''
Expand Down
54 changes: 0 additions & 54 deletions src/convenience.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,16 +704,6 @@ impl<'a, Args, Output> AsRef<Self> for dyn FnOnce<Args, Output = Output> + Send
self
}
}
impl<'a, A, Output> AsRef<Self> for dyn for<'r> FnOnce<(&'r A,), Output = Output> + 'a {
fn as_ref(&self) -> &Self {
self
}
}
impl<'a, A, Output> AsRef<Self> for dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send + 'a {
fn as_ref(&self) -> &Self {
self
}
}

impl<Args: 'static, Output: 'static> serde::ser::Serialize for dyn FnOnce<Args, Output = Output> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand Down Expand Up @@ -754,50 +744,6 @@ impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de>
.map(|x| x.0)
}
}
impl<A: 'static, Output: 'static> serde::ser::Serialize
for dyn for<'r> FnOnce<(&'r A,), Output = Output>
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serialize(self, serializer)
}
}
impl<'de, A: 'static, Output: 'static> serde::de::Deserialize<'de>
for boxed::Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + 'static>
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + 'static>>::deserialize(deserializer)
.map(|x| x.0)
}
}
impl<A: 'static, Output: 'static> serde::ser::Serialize
for dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serialize(self, serializer)
}
}
impl<'de, A: 'static, Output: 'static> serde::de::Deserialize<'de>
for boxed::Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send + 'static>
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send + 'static>>::deserialize(
deserializer,
)
.map(|x| x.0)
}
}

/// A convenience trait implemented on all (de)serializable implementors of [`std::ops::FnMut`].
///
Expand Down
11 changes: 6 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
//!
//! This crate currently requires Rust nightly.

#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.2.5")]
#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.2.6")]
#![feature(
arbitrary_self_types,
coerce_unsized,
Expand All @@ -119,10 +119,11 @@
unused_results,
clippy::pedantic
)] // from https://github.com/rust-unofficial/patterns/blob/master/anti_patterns/deny-warnings.md
#![allow(clippy::must_use_candidate, clippy::missing_errors_doc)]
// At some point this, and the HRTB Fn* impls, will be invalid
// See https://github.com/rust-lang/rust/issues/56105
#![allow(coherence_leak_check)]
#![allow(
clippy::must_use_candidate,
clippy::missing_errors_doc,
incomplete_features
)]

mod convenience;

Expand Down
123 changes: 58 additions & 65 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,44 @@
unused_results,
clippy::pedantic
)] // from https://github.com/rust-unofficial/patterns/blob/master/anti_patterns/deny-warnings.md
#![allow(clippy::unseparated_literal_suffix)]
#![allow(clippy::unseparated_literal_suffix, dead_code)]

use serde_closure::Fn;
use serde_derive::{Deserialize, Serialize};
use serde_traitobject as st;
use serde_traitobject::{Deserialize, Serialize};
use std::{any, env, process, rc};
use wasm_bindgen_test::wasm_bindgen_test;

#[derive(Serialize, Deserialize)]
struct Abc {
#[serde(with = "serde_traitobject")]
#[serde(with = "st")]
a: rc::Rc<dyn HelloSerialize>,
b: serde_traitobject::Rc<dyn HelloSerialize>,
#[serde(with = "serde_traitobject")]
b: st::Rc<dyn HelloSerialize>,
#[serde(with = "st")]
c: Box<dyn HelloSerialize>,
d: serde_traitobject::Box<dyn HelloSerialize>,
#[serde(with = "serde_traitobject")]
e: Box<dyn serde_traitobject::Any>,
f: serde_traitobject::Box<dyn serde_traitobject::Any>,
g: serde_traitobject::Box<dyn serde_traitobject::Fn(usize) -> String>,
h: serde_traitobject::Box<dyn serde_traitobject::Any>,
i: serde_traitobject::Box<dyn serde_traitobject::Any>,
j: serde_traitobject::Box<String>,
#[serde(with = "serde_traitobject")]
d: st::Box<dyn HelloSerialize>,
#[serde(with = "st")]
e: Box<dyn st::Any>,
f: st::Box<dyn st::Any>,
g: st::Box<dyn st::Fn(usize) -> String>,
h: st::Box<dyn st::Any>,
i: st::Box<dyn st::Any>,
j: st::Box<String>,
#[serde(with = "st")]
k: Box<String>,
l: serde_traitobject::Box<str>,
#[serde(with = "serde_traitobject")]
l: st::Box<str>,
#[serde(with = "st")]
m: Box<str>,
n: serde_traitobject::Box<[u16]>,
#[serde(with = "serde_traitobject")]
n: st::Box<[u16]>,
#[serde(with = "st")]
o: Box<[u16]>,
}

#[derive(Serialize)]
struct Def<'a> {
a: &'a (dyn serde_traitobject::FnOnce<(), Output = ()> + 'static),
c: &'a mut (dyn serde_traitobject::FnOnce<(), Output = ()> + 'static),
a: &'a (dyn st::FnOnce<(), Output = ()> + 'static),
c: &'a mut (dyn st::FnOnce<(), Output = ()> + 'static),
}

trait Hello {
Expand Down Expand Up @@ -76,7 +77,7 @@ impl Hello for u8 {

#[derive(Serialize)]
struct Ghi<'a> {
#[serde(with = "serde_traitobject")]
#[serde(with = "st")]
e: &'a (dyn Hello2Serialize + 'static),
}
trait Hello2 {}
Expand All @@ -88,6 +89,17 @@ impl<'a> AsRef<dyn Hello2Serialize + 'a> for dyn Hello2Serialize {
}
}

type Request = st::Box<dyn for<'a> st::FnOnce<(&'a String,), Output = ()> + Send>;

fn _assert() {
fn assert_serializable<T>()
where
T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
}
assert_serializable::<Request>();
}

#[wasm_bindgen_test]
#[allow(clippy::too_many_lines)]
fn main() {
Expand Down Expand Up @@ -122,17 +134,14 @@ fn main() {
);
assert_eq!(g(22), "hey 123!");
assert_eq!(
***Box::<dyn any::Any>::downcast::<serde_traitobject::Box<usize>>(h.into_any())
.unwrap(),
***Box::<dyn any::Any>::downcast::<st::Box<usize>>(h.into_any()).unwrap(),
987_654_321
);
assert_eq!(
*Box::<dyn any::Any>::downcast::<usize>(
Box::<dyn any::Any>::downcast::<serde_traitobject::Box<dyn serde_traitobject::Any>>(
i.into_any()
)
.unwrap()
.into_any()
Box::<dyn any::Any>::downcast::<st::Box<dyn st::Any>>(i.into_any())
.unwrap()
.into_any()
)
.unwrap(),
987_654_321
Expand All @@ -151,28 +160,24 @@ fn main() {
let a: Box<dyn any::Any> = *a;
let _: Box<usize> = Box::<dyn any::Any>::downcast(a).unwrap();

let a: serde_traitobject::Box<dyn serde_traitobject::Any> =
serde_traitobject::Box::new(serde_traitobject::Box::new(1usize)
as serde_traitobject::Box<dyn serde_traitobject::Any>);
let a: st::Box<dyn st::Any> = st::Box::new(st::Box::new(1usize) as st::Box<dyn st::Any>);
let a: Box<dyn any::Any> = a.into_any();
let a: Box<serde_traitobject::Box<dyn serde_traitobject::Any>> =
Box::<dyn any::Any>::downcast(a).unwrap();
let a: serde_traitobject::Box<dyn serde_traitobject::Any> = *a;
let a: Box<st::Box<dyn st::Any>> = Box::<dyn any::Any>::downcast(a).unwrap();
let a: st::Box<dyn st::Any> = *a;
let a: Box<dyn any::Any> = a.into_any();
let _: Box<usize> = Box::<dyn any::Any>::downcast(a).unwrap();

let original = Abc {
a: rc::Rc::new(123u16),
b: serde_traitobject::Rc::new(456u16),
b: st::Rc::new(456u16),
c: Box::new(789u32),
d: serde_traitobject::Box::new(101u8),
d: st::Box::new(101u8),
e: Box::new(78u8),
f: serde_traitobject::Box::new(78u8),
g: serde_traitobject::Box::new(Fn!(|a: usize| format!("hey {}!", a + 101))),
h: serde_traitobject::Box::new(serde_traitobject::Box::new(987_654_321usize)),
i: serde_traitobject::Box::new(serde_traitobject::Box::new(987_654_321usize)
as serde_traitobject::Box<dyn serde_traitobject::Any>),
j: serde_traitobject::Box::new(String::from("abc")),
f: st::Box::new(78u8),
g: st::Box::new(Fn!(|a: usize| format!("hey {}!", a + 101))),
h: st::Box::new(st::Box::new(987_654_321usize)),
i: st::Box::new(st::Box::new(987_654_321usize) as st::Box<dyn st::Any>),
j: st::Box::new(String::from("abc")),
k: Box::new(String::from("def")),
l: Into::<Box<str>>::into(String::from("ghi")).into(),
m: String::from("jkl").into(),
Expand All @@ -185,39 +190,27 @@ fn main() {
let a2 = bincode::deserialize(&a2).unwrap();
test(a1);
test(a2);
let a1 = serde_json::to_string(
&(serde_traitobject::Box::new(78u8)
as serde_traitobject::Box<dyn serde_traitobject::Debug>),
)
.unwrap();
let a1r: Result<serde_traitobject::Box<dyn serde_traitobject::Debug>, _> =
serde_json::from_str(&a1);
let a1 = serde_json::to_string(&(st::Box::new(78u8) as st::Box<dyn st::Debug>)).unwrap();
let a1r: Result<st::Box<dyn st::Debug>, _> = serde_json::from_str(&a1);
assert!(a1r.is_ok());
let a1r: Result<serde_traitobject::Box<dyn serde_traitobject::Any>, _> =
serde_json::from_str(&a1);
let a1r: Result<st::Box<dyn st::Any>, _> = serde_json::from_str(&a1);
assert!(a1r.is_err());
let a1 = bincode::serialize(
&(serde_traitobject::Box::new(78u8)
as serde_traitobject::Box<dyn serde_traitobject::Debug>),
)
.unwrap();
let a1: Result<serde_traitobject::Box<dyn serde_traitobject::Any>, _> =
bincode::deserialize(&a1);
let a1 = bincode::serialize(&(st::Box::new(78u8) as st::Box<dyn st::Debug>)).unwrap();
let a1: Result<st::Box<dyn st::Any>, _> = bincode::deserialize(&a1);
assert!(a1.is_err());
}

let original = Abc {
a: rc::Rc::new(123u16),
b: serde_traitobject::Rc::new(456u16),
b: st::Rc::new(456u16),
c: Box::new(789u32),
d: serde_traitobject::Box::new(101u8),
d: st::Box::new(101u8),
e: Box::new(78u8),
f: serde_traitobject::Box::new(78u8),
g: serde_traitobject::Box::new(Fn!(|a: usize| format!("hey {}!", a + 101))),
h: serde_traitobject::Box::new(serde_traitobject::Box::new(987_654_321usize)),
i: serde_traitobject::Box::new(serde_traitobject::Box::new(987_654_321usize)
as serde_traitobject::Box<dyn serde_traitobject::Any>),
j: serde_traitobject::Box::new(String::from("abc")),
f: st::Box::new(78u8),
g: st::Box::new(Fn!(|a: usize| format!("hey {}!", a + 101))),
h: st::Box::new(st::Box::new(987_654_321usize)),
i: st::Box::new(st::Box::new(987_654_321usize) as st::Box<dyn st::Any>),
j: st::Box::new(String::from("abc")),
k: Box::new(String::from("def")),
l: Into::<Box<str>>::into(String::from("ghi")).into(),
m: String::from("jkl").into(),
Expand Down

0 comments on commit 3a739ec

Please sign in to comment.