Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix on latest nightly #28

Merged
merged 2 commits into from
Jun 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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