Skip to content

Commit f1d9f03

Browse files
authored
Merge pull request #19 from alecmocatta/leak
Use pointer rather than reference to adhere to unsafe guidelines
2 parents c4d0310 + 013dedf commit f1d9f03

File tree

5 files changed

+23
-40
lines changed

5 files changed

+23
-40
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "serde_traitobject"
3-
version = "0.1.7"
3+
version = "0.1.8"
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.1.7"
15+
documentation = "https://docs.rs/serde_traitobject/0.1.8"
1616
readme = "README.md"
1717
edition = "2018"
1818

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
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.1.7/serde_traitobject/)
7+
[Docs](https://docs.rs/serde_traitobject/0.1.8/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.1.7/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.1.7/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.1.8/serde_traitobject/trait.Serialize.html) and [Deserialize](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Deserialize.html) traits as supertraits:
1616

1717
```rust
1818
trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
@@ -28,12 +28,12 @@ struct Message(#[serde(with = "serde_traitobject")] Box<dyn MyTrait>);
2828
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.
2929

3030
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.1.7/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/fn.deserialize.html) functions;
32-
* The [Box](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/struct.Arc.html) structs, which are simple wrappers around their stdlib counterparts that automatically handle (de)serialization without needing the above annotation;
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.1.8/serde_traitobject/fn.serialize.html) and [deserialize](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/fn.deserialize.html) functions;
32+
* The [Box](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/struct.Box.html), [Rc](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/struct.Rc.html) and [Arc](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/struct.Arc.html) structs, which are simple wrappers around their stdlib counterparts that automatically handle (de)serialization without needing the above annotation;
3333

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

36-
* [Any](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.1.7/serde_traitobject/trait.FnOnce.html)
36+
* [Any](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Any.html), [Debug](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Debug.html), [Display](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Display.html), [Error](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Error.html), [Fn](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.Fn.html), [FnMut](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.FnMut.html), [FnOnce](https://docs.rs/serde_traitobject/0.1.8/serde_traitobject/trait.FnOnce.html)
3737

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

azure-pipelines.yml

+1-1
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-08-15
17+
rust_lint_toolchain: nightly-2019-10-15
1818
rust_flags: ''
1919
rust_features: ''
2020
rust_target_check: ''

src/lib.rs

+14-32
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//!
1111
//! ```
1212
//! # use serde_derive::{Serialize, Deserialize};
13-
//! # fn main() {
1413
//! trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
1514
//! fn my_method(&self);
1615
//! }
@@ -19,7 +18,6 @@
1918
//! struct Message(#[serde(with = "serde_traitobject")] Box<dyn MyTrait>);
2019
//!
2120
//! // Woohoo, `Message` is now serializable!
22-
//! # }
2321
//! ```
2422
//!
2523
//! 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.
@@ -36,7 +34,6 @@
3634
//!
3735
//! ```
3836
//! # use serde_derive::{Serialize, Deserialize};
39-
//! # fn main() {
4037
//! use std::any::Any;
4138
//! use serde_traitobject as s;
4239
//!
@@ -61,7 +58,6 @@
6158
//! println!("{:?}", downcast);
6259
//! # assert_eq!(format!("{:?}", downcast), "MyStruct { foo: \"abc\", bar: 123 }");
6360
//! // MyStruct { foo: "abc", bar: 123 }
64-
//! # }
6561
//! ```
6662
//!
6763
//! # Security
@@ -98,8 +94,9 @@
9894
//!
9995
//! This crate currently requires Rust nightly.
10096
101-
#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.1.7")]
97+
#![doc(html_root_url = "https://docs.rs/serde_traitobject/0.1.8")]
10298
#![feature(
99+
arbitrary_self_types,
103100
coerce_unsized,
104101
core_intrinsics,
105102
fn_traits,
@@ -138,32 +135,27 @@ pub use convenience::*;
138135
/// ```
139136
/// use serde_derive::{Serialize, Deserialize};
140137
///
141-
/// # fn main() {
142138
/// trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
143139
/// fn my_method(&self);
144140
/// }
145-
/// # }
146141
/// ```
147142
///
148143
/// Now your trait object is serializable!
149144
/// ```
150145
/// # use serde_derive::{Serialize, Deserialize};
151146
/// #
152-
/// # fn main() {
153147
/// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
154148
/// # fn my_method(&self);
155149
/// # }
156150
/// #[derive(Serialize, Deserialize)]
157151
/// struct Message(#[serde(with = "serde_traitobject")] Box<dyn MyTrait>);
158152
///
159153
/// // Woohoo, `Message` is now serializable!
160-
/// # }
161154
/// ```
162155
///
163156
/// Any implementers of `MyTrait` would now have to themselves implement `serde::Serialize` and `serde::de::DeserializeOwned`. This would typically be through `serde_derive`, like:
164157
/// ```
165158
/// # use serde_derive::{Serialize, Deserialize};
166-
/// # fn main() {
167159
/// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
168160
/// # fn my_method(&self);
169161
/// # }
@@ -179,7 +171,6 @@ pub use convenience::*;
179171
/// println!("foo: {}", self.foo);
180172
/// }
181173
/// }
182-
/// # }
183174
/// ```
184175
pub trait Serialize: serialize::Sealed {}
185176
impl<T: serde::ser::Serialize + ?Sized> Serialize for T {}
@@ -192,32 +183,27 @@ impl<T: serde::ser::Serialize + ?Sized> Serialize for T {}
192183
/// ```
193184
/// use serde_derive::{Serialize, Deserialize};
194185
///
195-
/// # fn main() {
196186
/// trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
197187
/// fn my_method(&self);
198188
/// }
199-
/// # }
200189
/// ```
201190
///
202191
/// Now your trait object is serializable!
203192
/// ```
204193
/// # use serde_derive::{Serialize, Deserialize};
205194
/// #
206-
/// # fn main() {
207195
/// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
208196
/// # fn my_method(&self);
209197
/// # }
210198
/// #[derive(Serialize, Deserialize)]
211199
/// struct Message(#[serde(with = "serde_traitobject")] Box<dyn MyTrait>);
212200
///
213201
/// // Woohoo, `Message` is now serializable!
214-
/// # }
215202
/// ```
216203
///
217204
/// Any implementers of `MyTrait` would now have to themselves implement `serde::Serialize` and `serde::de::DeserializeOwned`. This would typically be through `serde_derive`, like:
218205
/// ```
219206
/// # use serde_derive::{Serialize, Deserialize};
220-
/// # fn main() {
221207
/// # trait MyTrait: serde_traitobject::Serialize + serde_traitobject::Deserialize {
222208
/// # fn my_method(&self);
223209
/// # }
@@ -233,7 +219,6 @@ impl<T: serde::ser::Serialize + ?Sized> Serialize for T {}
233219
/// println!("foo: {}", self.foo);
234220
/// }
235221
/// }
236-
/// # }
237222
/// ```
238223
pub trait Deserialize: deserialize::Sealed {}
239224
impl<T: serde::de::DeserializeOwned> Deserialize for T {}
@@ -283,7 +268,7 @@ mod deserialize {
283268
/// Unsafe as it `ptr::write`s into `&mut self`, assuming it to be uninitialized
284269
#[inline(always)]
285270
unsafe fn deserialize_erased(
286-
&mut self, deserializer: &mut dyn erased_serde::Deserializer,
271+
self: *mut Self, deserializer: &mut dyn erased_serde::Deserializer,
287272
) -> Result<(), erased_serde::Error> {
288273
let _ = deserializer;
289274
unreachable!()
@@ -308,7 +293,7 @@ mod deserialize {
308293
impl<T: serde::de::DeserializeOwned> Sealed for T {
309294
#[inline(always)]
310295
unsafe fn deserialize_erased(
311-
&mut self, deserializer: &mut dyn erased_serde::Deserializer,
296+
self: *mut Self, deserializer: &mut dyn erased_serde::Deserializer,
312297
) -> Result<(), erased_serde::Error> {
313298
erased_serde::deserialize(deserializer).map(|x| ptr::write(self, x))
314299
}
@@ -453,7 +438,7 @@ impl<T: Deserialize + ?Sized + 'static> DeserializerTrait<T> for Deserializer<T>
453438
});
454439
let t1: u64 = match seq.next_element()? {
455440
Some(value) => value,
456-
None => return Err(serde::de::Error::invalid_length(1, &self)),
441+
None => return Err(serde::de::Error::invalid_length(1, &self)), // TODO: don't leak uninitialized box
457442
};
458443
assert_eq!(t1, object.type_id(), "Deserializing the trait object \"{}\" failed in a way that should never happen. Please file an issue! https://github.com/alecmocatta/serde_traitobject/issues/new", type_name::<T>());
459444
let t2: boxed::Box<T> = match seq
@@ -477,11 +462,16 @@ impl<'de, T: Deserialize + ?Sized> serde::de::DeserializeSeed<'de> for Deseriali
477462
D: serde::de::Deserializer<'de>,
478463
{
479464
let mut x = self.0;
480-
unsafe {
481-
(&mut *x).deserialize_erased(&mut erased_serde::Deserializer::erase(deserializer))
465+
let x_ptr: *mut T = &mut *x;
466+
match unsafe {
467+
x_ptr.deserialize_erased(&mut erased_serde::Deserializer::erase(deserializer))
468+
} {
469+
Ok(()) => Ok(x),
470+
Err(err) => {
471+
mem::forget(x); // TODO: don't leak uninitialized box
472+
Err(serde::de::Error::custom(err))
473+
}
482474
}
483-
.map(|()| x)
484-
.map_err(serde::de::Error::custom)
485475
}
486476
}
487477

@@ -491,26 +481,22 @@ impl<'de, T: Deserialize + ?Sized> serde::de::DeserializeSeed<'de> for Deseriali
491481
/// ```
492482
/// # use serde_derive::{Serialize, Deserialize};
493483
///
494-
/// # fn main() {
495484
/// #[derive(Serialize, Deserialize)]
496485
/// struct MyStruct {
497486
/// #[serde(with = "serde_traitobject")]
498487
/// field: Box<dyn serde_traitobject::Any>,
499488
/// }
500-
/// # }
501489
/// ```
502490
///
503491
/// Or, alternatively, if only Serialize is desired:
504492
/// ```
505493
/// # use serde_derive::{Serialize, Deserialize};
506494
///
507-
/// # fn main() {
508495
/// #[derive(Serialize)]
509496
/// struct MyStruct {
510497
/// #[serde(serialize_with = "serde_traitobject::serialize")]
511498
/// field: Box<dyn serde_traitobject::Any>,
512499
/// }
513-
/// # }
514500
/// ```
515501
pub fn serialize<T: Serialize + ?Sized + 'static, B: AsRef<T> + ?Sized, S>(
516502
t: &B, serializer: S,
@@ -527,26 +513,22 @@ where
527513
/// ```
528514
/// # use serde_derive::{Serialize, Deserialize};
529515
///
530-
/// # fn main() {
531516
/// #[derive(Serialize, Deserialize)]
532517
/// struct MyStruct {
533518
/// #[serde(with = "serde_traitobject")]
534519
/// field: Box<dyn serde_traitobject::Any>,
535520
/// }
536-
/// # }
537521
/// ```
538522
///
539523
/// Or, alternatively, if only Deserialize is desired:
540524
/// ```
541525
/// # use serde_derive::{Serialize, Deserialize};
542526
///
543-
/// # fn main() {
544527
/// #[derive(Deserialize)]
545528
/// struct MyStruct {
546529
/// #[serde(deserialize_with = "serde_traitobject::deserialize")]
547530
/// field: Box<dyn serde_traitobject::Any>,
548531
/// }
549-
/// # }
550532
/// ```
551533
pub fn deserialize<'de, T: Deserialize + ?Sized + 'static, B, D>(
552534
deserializer: D,

tests/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ impl Hello for u8 {
6666
}
6767
}
6868

69+
#[allow(clippy::too_many_lines)]
6970
fn main() {
7071
let test = |Abc {
7172
a,

0 commit comments

Comments
 (0)