Skip to content

Commit d1a59ff

Browse files
authored
Merge pull request #25 from alecmocatta/conversion-methods
Conversion methods
2 parents 494d1fb + 3fad4c6 commit d1a59ff

File tree

7 files changed

+62
-22
lines changed

7 files changed

+62
-22
lines changed

.editorconfig

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[*]
2+
tab_width = 4
3+
4+
[.*]
5+
tab_width = 4

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "serde_traitobject"
3-
version = "0.2.3"
3+
version = "0.2.4"
44
license = "MIT OR Apache-2.0"
55
authors = ["Alec Mocatta <[email protected]>"]
66
categories = ["development-tools","encoding","rust-patterns","network-programming"]
@@ -12,7 +12,7 @@ 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.3"
15+
documentation = "https://docs.rs/serde_traitobject/0.2.4"
1616
readme = "README.md"
1717
edition = "2018"
1818

@@ -31,6 +31,7 @@ serde_derive = "1.0"
3131
serde_json = "1.0"
3232
bincode = "1.0"
3333
serde_closure = "0.2.2"
34+
wasm-bindgen-test = "0.3"
3435

3536
[[test]]
3637
name = "test"

README.md

+16-11
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,39 @@
44
[![MIT / Apache 2.0 licensed](https://img.shields.io/crates/l/serde_traitobject.svg?maxAge=2592000)](#License)
55
[![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)
66

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

1717
```rust
1818
trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
19-
fn my_method(&self);
19+
fn my_method(&self);
2020
}
2121

2222
#[derive(Serialize, Deserialize)]
23-
struct Message(#[serde(with = "serde_traitobject")] Box<dyn MyTrait>);
23+
struct Message {
24+
#[serde(with = "serde_traitobject")]
25+
message: Box<dyn MyTrait>,
26+
}
2427

2528
// Woohoo, `Message` is now serializable!
2629
```
2730

2831
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.
2932

3033
There are two ways to (de)serialize your trait object:
31-
* 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.3/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.2.3/serde_traitobject/fn.deserialize.html) functions;
32-
* The [Box](https://docs.rs/serde_traitobject/0.2.3/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.2.3/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.2.3/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.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;
3336

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

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

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

@@ -43,13 +46,13 @@ use serde_traitobject as s;
4346

4447
#[derive(Serialize, Deserialize, Debug)]
4548
struct MyStruct {
46-
foo: String,
47-
bar: usize,
49+
foo: String,
50+
bar: usize,
4851
}
4952

5053
let my_struct = MyStruct {
51-
foo: String::from("abc"),
52-
bar: 123,
54+
foo: String::from("abc"),
55+
bar: 123,
5356
};
5457

5558
let erased: s::Box<dyn s::Any> = s::Box::new(my_struct);
@@ -69,6 +72,8 @@ This crate works by wrapping the vtable pointer with [`relative::Vtable`](https:
6972

7073
This approach is not yet secure against malicious actors. However, if we assume non-malicious actors and typical (static or dynamic) linking conditions, then it's not unreasonable to consider it sound.
7174

75+
See [here](https://github.com/rust-lang/rust/pull/66113) for ongoing work in `rustc` to make this safe and secure.
76+
7277
### Validation
7378

7479
Three things are serialized alongside the vtable pointer for the purpose of validation:

azure-pipelines.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
endpoint: alecmocatta
1515
default:
1616
rust_toolchain: nightly
17-
rust_lint_toolchain: nightly-2019-10-17
17+
rust_lint_toolchain: nightly-2019-11-24
1818
rust_flags: ''
1919
rust_features: ''
2020
rust_target_check: ''
@@ -29,4 +29,4 @@ jobs:
2929
rust_target_run: 'x86_64-apple-darwin i686-apple-darwin'
3030
linux:
3131
imageName: 'ubuntu-16.04'
32-
rust_target_run: 'x86_64-unknown-linux-gnu i686-unknown-linux-gnu x86_64-unknown-linux-musl i686-unknown-linux-musl'
32+
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

+18
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ impl Box<dyn Any + Send + Sync> {
5252
}
5353
}
5454
}
55+
impl dyn Any + Send {
56+
/// Convert into a `std::boxed::Box<dyn std::any::Any + Send>`.
57+
pub fn into_any_send(self: boxed::Box<Self>) -> boxed::Box<dyn any::Any + Send> {
58+
<Box<dyn Any + Send>>::into_any_send(Box(self))
59+
}
60+
}
61+
impl dyn Any + Sync {
62+
/// Convert into a `std::boxed::Box<dyn std::any::Any + Sync>`.
63+
pub fn into_any_sync(self: boxed::Box<Self>) -> boxed::Box<dyn any::Any + Sync> {
64+
<Box<dyn Any + Sync>>::into_any_sync(Box(self))
65+
}
66+
}
67+
impl dyn Any + Send + Sync {
68+
/// Convert into a `std::boxed::Box<dyn std::any::Any + Send + Sync>`.
69+
pub fn into_any_send_sync(self: boxed::Box<Self>) -> boxed::Box<dyn any::Any + Send + Sync> {
70+
<Box<dyn Any + Send + Sync>>::into_any_send_sync(Box(self))
71+
}
72+
}
5573
impl<T: ?Sized + marker::Unsize<U>, U: ?Sized> ops::CoerceUnsized<Box<U>> for Box<T> {}
5674
impl<T: ?Sized> Deref for Box<T> {
5775
type Target = boxed::Box<T>;

src/lib.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
//! ```
1212
//! # use serde_derive::{Serialize, Deserialize};
1313
//! trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
14-
//! fn my_method(&self);
14+
//! fn my_method(&self);
1515
//! }
1616
//!
1717
//! #[derive(Serialize, Deserialize)]
18-
//! struct Message(#[serde(with = "serde_traitobject")] Box<dyn MyTrait>);
18+
//! struct Message {
19+
//! #[serde(with = "serde_traitobject")]
20+
//! message: Box<dyn MyTrait>,
21+
//! }
1922
//!
2023
//! // Woohoo, `Message` is now serializable!
2124
//! ```
@@ -39,13 +42,13 @@
3942
//!
4043
//! #[derive(Serialize, Deserialize, Debug)]
4144
//! struct MyStruct {
42-
//! foo: String,
43-
//! bar: usize,
45+
//! foo: String,
46+
//! bar: usize,
4447
//! }
4548
//!
4649
//! let my_struct = MyStruct {
47-
//! foo: String::from("abc"),
48-
//! bar: 123,
50+
//! foo: String::from("abc"),
51+
//! bar: 123,
4952
//! };
5053
//!
5154
//! let erased: s::Box<dyn s::Any> = s::Box::new(my_struct);
@@ -66,6 +69,8 @@
6669
//!
6770
//! This approach is not yet secure against malicious actors. However, if we assume non-malicious actors and typical (static or dynamic) linking conditions, then it's not unreasonable to consider it sound.
6871
//!
72+
//! See [here](https://github.com/rust-lang/rust/pull/66113) for ongoing work in `rustc` to make this safe and secure.
73+
//!
6974
//! ## Validation
7075
//!
7176
//! Three things are serialized alongside the vtable pointer for the purpose of validation:
@@ -94,7 +99,7 @@
9499
//!
95100
//! This crate currently requires Rust nightly.
96101
97-
#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.2.3")]
102+
#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.2.4")]
98103
#![feature(
99104
arbitrary_self_types,
100105
coerce_unsized,

tests/test.rs

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use serde_closure::Fn;
1616
use serde_derive::{Deserialize, Serialize};
1717
use serde_traitobject::{Deserialize, Serialize};
1818
use std::{any, env, process, rc};
19+
use wasm_bindgen_test::wasm_bindgen_test;
1920

2021
#[derive(Serialize, Deserialize)]
2122
struct Abc {
@@ -87,6 +88,7 @@ impl<'a> AsRef<dyn Hello2Serialize + 'a> for dyn Hello2Serialize {
8788
}
8889
}
8990

91+
#[wasm_bindgen_test]
9092
#[allow(clippy::too_many_lines)]
9193
fn main() {
9294
let test = |Abc {
@@ -223,6 +225,10 @@ fn main() {
223225
o: vec![1u16, 2, 3].into(),
224226
};
225227

228+
if cfg!(target_arch = "wasm32") {
229+
return;
230+
}
231+
226232
if let Ok(x) = env::var("SERDE_TRAITOBJECT_SPAWNED") {
227233
let (a, bc): (_, Vec<u8>) = serde_json::from_str(&x).unwrap();
228234
eq(&original, &a);

0 commit comments

Comments
 (0)