Skip to content

Commit aa553ab

Browse files
authored
Merge pull request #27 from alecmocatta/hrtb-fn
Workaround dyn Fn* with reference arguments (HRTB) not being (de)serializable
2 parents d1a59ff + 1ffab5d commit aa553ab

File tree

5 files changed

+116
-57
lines changed

5 files changed

+116
-57
lines changed

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "serde_traitobject"
3-
version = "0.2.4"
3+
version = "0.2.5"
44
license = "MIT OR Apache-2.0"
55
authors = ["Alec Mocatta <[email protected]>"]
66
categories = ["development-tools","encoding","rust-patterns","network-programming"]
@@ -12,12 +12,12 @@ This library enables the serialization and deserialization of trait objects such
1212
"""
1313
repository = "https://github.com/alecmocatta/serde_traitobject"
1414
homepage = "https://github.com/alecmocatta/serde_traitobject"
15-
documentation = "https://docs.rs/serde_traitobject/0.2.4"
15+
documentation = "https://docs.rs/serde_traitobject/0.2.5"
1616
readme = "README.md"
1717
edition = "2018"
1818

1919
[badges]
20-
azure-devops = { project = "alecmocatta/serde_traitobject", pipeline = "tests" }
20+
azure-devops = { project = "alecmocatta/serde_traitobject", pipeline = "tests", build = "9" }
2121
maintenance = { status = "actively-developed" }
2222

2323
[dependencies]

README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
[![Crates.io](https://img.shields.io/crates/v/serde_traitobject.svg?maxAge=86400)](https://crates.io/crates/serde_traitobject)
44
[![MIT / Apache 2.0 licensed](https://img.shields.io/crates/l/serde_traitobject.svg?maxAge=2592000)](#License)
5-
[![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)
5+
[![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)
66

7-
[Docs](https://docs.rs/serde_traitobject/0.2.4/serde_traitobject/)
7+
[📖 Docs](https://docs.rs/serde_traitobject/0.2.5/serde_traitobject/) | [💬 Chat](https://constellation.zulipchat.com/#narrow/stream/213236-subprojects)
88

99
**Serializable and deserializable trait objects.**
1010

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

1313
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.
1414

15-
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.4/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.2.4/serde_traitobject/trait.Deserialize.html) traits as supertraits:
15+
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:
1616

1717
```rust
1818
trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
@@ -31,12 +31,12 @@ struct Message {
3131
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.
3232

3333
There are two ways to (de)serialize your trait object:
34-
* 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.4/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.2.4/serde_traitobject/fn.deserialize.html) functions;
35-
* The [Box](https://docs.rs/serde_traitobject/0.2.4/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.2.4/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.2.4/serde_traitobject/struct.Arc.html) structs, which are simple wrappers around their stdlib counterparts that automatically handle (de)serialization without needing the above annotation;
34+
* 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;
35+
* 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;
3636

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

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

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

azure-pipelines.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ jobs:
1414
endpoint: alecmocatta
1515
default:
1616
rust_toolchain: nightly
17-
rust_lint_toolchain: nightly-2019-11-24
17+
rust_lint_toolchain: nightly-2020-06-10
1818
rust_flags: ''
1919
rust_features: ''
2020
rust_target_check: ''
2121
rust_target_build: ''
2222
rust_target_run: ''
2323
matrix:
2424
windows:
25-
imageName: 'vs2017-win2016'
26-
rust_target_run: 'x86_64-pc-windows-msvc i686-pc-windows-msvc' # currently broken building crate-type=lib: x86_64-pc-windows-gnu i686-pc-windows-gnu
25+
imageName: 'windows-latest'
26+
rust_target_run: 'x86_64-pc-windows-msvc i686-pc-windows-msvc x86_64-pc-windows-gnu'
2727
mac:
28-
imageName: 'macos-10.13'
29-
rust_target_run: 'x86_64-apple-darwin i686-apple-darwin'
28+
imageName: 'macos-latest'
29+
rust_target_run: 'x86_64-apple-darwin'
3030
linux:
31-
imageName: 'ubuntu-16.04'
31+
imageName: 'ubuntu-latest'
3232
rust_target_run: 'x86_64-unknown-linux-gnu i686-unknown-linux-gnu x86_64-unknown-linux-musl i686-unknown-linux-musl wasm32-unknown-unknown'

src/convenience.rs

+63-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use super::{deserialize, serialize, Deserialize, Serialize};
2-
use serde;
31
use std::{
42
any, borrow::{Borrow, BorrowMut}, boxed, error, fmt, marker, ops::{self, Deref, DerefMut}, rc, sync
53
};
64

5+
use super::{deserialize, serialize, Deserialize, Serialize};
6+
77
/// Convenience wrapper around [std::boxed::Box<T>](std::boxed::Box) that automatically uses `serde_traitobject` for (de)serialization.
88
#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
99
pub struct Box<T: ?Sized>(boxed::Box<T>);
@@ -128,6 +128,7 @@ impl<T> From<T> for Box<T> {
128128
}
129129
}
130130
impl<T: error::Error> error::Error for Box<T> {
131+
#[allow(deprecated)]
131132
fn description(&self) -> &str {
132133
error::Error::description(&**self)
133134
}
@@ -472,14 +473,14 @@ impl<'de> serde::de::Deserialize<'de> for boxed::Box<dyn Any + Send + 'static> {
472473
/// #[derive(Serialize,Deserialize,Debug)]
473474
/// struct MyError(String);
474475
/// impl fmt::Display for MyError {
475-
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476-
/// write!(f, "{}", self.0)
477-
/// }
476+
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
477+
/// write!(f, "{}", self.0)
478+
/// }
478479
/// }
479480
/// impl std::error::Error for MyError {}
480481
///
481482
/// fn fallible() -> Result<(),s::Box<dyn s::Error>> {
482-
/// Err(Box::new(MyError(String::from("boxed error"))) as Box<dyn s::Error>)?
483+
/// Err(Box::new(MyError(String::from("boxed error"))) as Box<dyn s::Error>)?
483484
/// }
484485
///
485486
/// let serialized = serde_json::to_string(&fallible()).unwrap();
@@ -561,7 +562,7 @@ impl<'de> serde::de::Deserialize<'de> for boxed::Box<dyn Error + Send + 'static>
561562
/// extern crate serde_traitobject as s;
562563
///
563564
/// fn message() -> s::Box<dyn s::Display> {
564-
/// s::Box::new(String::from("boxed displayable"))
565+
/// s::Box::new(String::from("boxed displayable"))
565566
/// }
566567
///
567568
/// let serialized = serde_json::to_string(&message()).unwrap();
@@ -630,7 +631,7 @@ impl<'de> serde::de::Deserialize<'de> for boxed::Box<dyn Display + Send + 'stati
630631
/// extern crate serde_traitobject as s;
631632
///
632633
/// fn debug() -> s::Box<dyn s::Debug> {
633-
/// s::Box::new(String::from("boxed debuggable"))
634+
/// s::Box::new(String::from("boxed debuggable"))
634635
/// }
635636
///
636637
/// let serialized = serde_json::to_string(&debug()).unwrap();
@@ -703,6 +704,16 @@ impl<'a, Args, Output> AsRef<Self> for dyn FnOnce<Args, Output = Output> + Send
703704
self
704705
}
705706
}
707+
impl<'a, A, Output> AsRef<Self> for dyn for<'r> FnOnce<(&'r A,), Output = Output> + 'a {
708+
fn as_ref(&self) -> &Self {
709+
self
710+
}
711+
}
712+
impl<'a, A, Output> AsRef<Self> for dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send + 'a {
713+
fn as_ref(&self) -> &Self {
714+
self
715+
}
716+
}
706717

707718
impl<Args: 'static, Output: 'static> serde::ser::Serialize for dyn FnOnce<Args, Output = Output> {
708719
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -743,6 +754,50 @@ impl<'de, Args: 'static, Output: 'static> serde::de::Deserialize<'de>
743754
.map(|x| x.0)
744755
}
745756
}
757+
impl<A: 'static, Output: 'static> serde::ser::Serialize
758+
for dyn for<'r> FnOnce<(&'r A,), Output = Output>
759+
{
760+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
761+
where
762+
S: serde::Serializer,
763+
{
764+
serialize(self, serializer)
765+
}
766+
}
767+
impl<'de, A: 'static, Output: 'static> serde::de::Deserialize<'de>
768+
for boxed::Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + 'static>
769+
{
770+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
771+
where
772+
D: serde::Deserializer<'de>,
773+
{
774+
<Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + 'static>>::deserialize(deserializer)
775+
.map(|x| x.0)
776+
}
777+
}
778+
impl<A: 'static, Output: 'static> serde::ser::Serialize
779+
for dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send
780+
{
781+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
782+
where
783+
S: serde::Serializer,
784+
{
785+
serialize(self, serializer)
786+
}
787+
}
788+
impl<'de, A: 'static, Output: 'static> serde::de::Deserialize<'de>
789+
for boxed::Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send + 'static>
790+
{
791+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
792+
where
793+
D: serde::Deserializer<'de>,
794+
{
795+
<Box<dyn for<'r> FnOnce<(&'r A,), Output = Output> + Send + 'static>>::deserialize(
796+
deserializer,
797+
)
798+
.map(|x| x.0)
799+
}
800+
}
746801

747802
/// A convenience trait implemented on all (de)serializable implementors of [`std::ops::FnMut`].
748803
///

0 commit comments

Comments
 (0)