Skip to content

Commit eba735a

Browse files
authored
Merge pull request #117 from dtolnay/dangle
Allow underlying serializer to dangle during erased serializer drop
2 parents a9128c1 + 0d5413b commit eba735a

File tree

3 files changed

+106
-73
lines changed

3 files changed

+106
-73
lines changed

src/de.rs

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -224,39 +224,41 @@ pub trait EnumAccess<'de> {
224224
}
225225

226226
impl<'de> dyn Deserializer<'de> {
227-
/// Convert any Serde `Deserializer` to a trait object.
228-
///
229-
/// ```rust
230-
/// use erased_serde::Deserializer;
231-
/// use std::collections::BTreeMap as Map;
232-
///
233-
/// fn main() {
234-
/// static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
235-
/// static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
236-
///
237-
/// // Construct some deserializers.
238-
/// let json = &mut serde_json::Deserializer::from_slice(JSON);
239-
/// let cbor = &mut serde_cbor::Deserializer::from_slice(CBOR);
240-
///
241-
/// // The values in this map are boxed trait objects, which is not possible
242-
/// // with the normal serde::Deserializer because of object safety.
243-
/// let mut formats: Map<&str, Box<dyn Deserializer>> = Map::new();
244-
/// formats.insert("json", Box::new(<dyn Deserializer>::erase(json)));
245-
/// formats.insert("cbor", Box::new(<dyn Deserializer>::erase(cbor)));
246-
///
247-
/// // Pick a Deserializer out of the formats map.
248-
/// let format = formats.get_mut("json").unwrap();
249-
///
250-
/// let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
251-
///
252-
/// println!("{}", data["A"] + data["B"]);
253-
/// }
254-
/// ```
255-
pub fn erase<D>(deserializer: D) -> impl Deserializer<'de>
256-
where
257-
D: serde::Deserializer<'de>,
258-
{
259-
erase::Deserializer::new(deserializer)
227+
return_impl_trait! {
228+
/// Convert any Serde `Deserializer` to a trait object.
229+
///
230+
/// ```rust
231+
/// use erased_serde::Deserializer;
232+
/// use std::collections::BTreeMap as Map;
233+
///
234+
/// fn main() {
235+
/// static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
236+
/// static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
237+
///
238+
/// // Construct some deserializers.
239+
/// let json = &mut serde_json::Deserializer::from_slice(JSON);
240+
/// let cbor = &mut serde_cbor::Deserializer::from_slice(CBOR);
241+
///
242+
/// // The values in this map are boxed trait objects, which is not possible
243+
/// // with the normal serde::Deserializer because of object safety.
244+
/// let mut formats: Map<&str, Box<dyn Deserializer>> = Map::new();
245+
/// formats.insert("json", Box::new(<dyn Deserializer>::erase(json)));
246+
/// formats.insert("cbor", Box::new(<dyn Deserializer>::erase(cbor)));
247+
///
248+
/// // Pick a Deserializer out of the formats map.
249+
/// let format = formats.get_mut("json").unwrap();
250+
///
251+
/// let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
252+
///
253+
/// println!("{}", data["A"] + data["B"]);
254+
/// }
255+
/// ```
256+
pub fn erase<D>(deserializer: D) -> impl Deserializer<'de> [erase::Deserializer<D>]
257+
where
258+
D: serde::Deserializer<'de>,
259+
{
260+
erase::Deserializer::new(deserializer)
261+
}
260262
}
261263
}
262264

@@ -1657,4 +1659,11 @@ mod tests {
16571659
assert::<Box<dyn Deserializer + Send + Sync>>();
16581660
assert::<Box<dyn Deserializer + Sync + Send>>();
16591661
}
1662+
1663+
#[test]
1664+
fn test_dangle() {
1665+
let mut json_deserializer = serde_json::Deserializer::from_str("");
1666+
let _erased_deserializer = <dyn Deserializer>::erase(&mut json_deserializer);
1667+
drop(json_deserializer);
1668+
}
16601669
}

src/macros.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,21 @@ macro_rules! __internal_serialize_trait_object {
115115
};
116116
}
117117

118+
macro_rules! return_impl_trait {
119+
(
120+
$(#[$attr:meta])*
121+
$vis:vis fn $name:ident <$param:ident> $args:tt -> $impl_trait:ty [$concrete:ty] $($body:tt)+
122+
) => {
123+
#[cfg(not(docsrs))]
124+
$(#[$attr])*
125+
$vis fn $name <$param> $args -> $concrete $($body)+
126+
127+
#[cfg(docsrs)]
128+
$(#[$attr])*
129+
$vis fn $name <$param> $args -> $impl_trait $($body)+
130+
};
131+
}
132+
118133
// TEST ////////////////////////////////////////////////////////////////////////
119134

120135
#[cfg(test)]

src/ser.rs

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -183,46 +183,48 @@ pub trait Serializer: sealed::serializer::Sealed {
183183
}
184184

185185
impl dyn Serializer {
186-
/// Convert any Serde `Serializer` to a trait object.
187-
///
188-
/// ```rust
189-
/// use erased_serde::{Serialize, Serializer};
190-
/// use std::collections::BTreeMap as Map;
191-
/// use std::io;
192-
///
193-
/// fn main() {
194-
/// // Construct some serializers.
195-
/// let json = &mut serde_json::Serializer::new(io::stdout());
196-
/// let cbor = &mut serde_cbor::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));
197-
///
198-
/// // The values in this map are boxed trait objects. Ordinarily this would not
199-
/// // be possible with serde::Serializer because of object safety, but type
200-
/// // erasure makes it possible with erased_serde::Serializer.
201-
/// let mut formats: Map<&str, Box<dyn Serializer>> = Map::new();
202-
/// formats.insert("json", Box::new(<dyn Serializer>::erase(json)));
203-
/// formats.insert("cbor", Box::new(<dyn Serializer>::erase(cbor)));
204-
///
205-
/// // These are boxed trait objects as well. Same thing here - type erasure
206-
/// // makes this possible.
207-
/// let mut values: Map<&str, Box<dyn Serialize>> = Map::new();
208-
/// values.insert("vec", Box::new(vec!["a", "b"]));
209-
/// values.insert("int", Box::new(65536));
210-
///
211-
/// // Pick a Serializer out of the formats map.
212-
/// let format = formats.get_mut("json").unwrap();
213-
///
214-
/// // Pick a Serialize out of the values map.
215-
/// let value = values.get("vec").unwrap();
216-
///
217-
/// // This line prints `["a","b"]` to stdout.
218-
/// value.erased_serialize(format).unwrap();
219-
/// }
220-
/// ```
221-
pub fn erase<S>(serializer: S) -> impl Serializer
222-
where
223-
S: serde::Serializer,
224-
{
225-
erase::Serializer::new(serializer)
186+
return_impl_trait! {
187+
/// Convert any Serde `Serializer` to a trait object.
188+
///
189+
/// ```rust
190+
/// use erased_serde::{Serialize, Serializer};
191+
/// use std::collections::BTreeMap as Map;
192+
/// use std::io;
193+
///
194+
/// fn main() {
195+
/// // Construct some serializers.
196+
/// let json = &mut serde_json::Serializer::new(io::stdout());
197+
/// let cbor = &mut serde_cbor::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));
198+
///
199+
/// // The values in this map are boxed trait objects. Ordinarily this would not
200+
/// // be possible with serde::Serializer because of object safety, but type
201+
/// // erasure makes it possible with erased_serde::Serializer.
202+
/// let mut formats: Map<&str, Box<dyn Serializer>> = Map::new();
203+
/// formats.insert("json", Box::new(<dyn Serializer>::erase(json)));
204+
/// formats.insert("cbor", Box::new(<dyn Serializer>::erase(cbor)));
205+
///
206+
/// // These are boxed trait objects as well. Same thing here - type erasure
207+
/// // makes this possible.
208+
/// let mut values: Map<&str, Box<dyn Serialize>> = Map::new();
209+
/// values.insert("vec", Box::new(vec!["a", "b"]));
210+
/// values.insert("int", Box::new(65536));
211+
///
212+
/// // Pick a Serializer out of the formats map.
213+
/// let format = formats.get_mut("json").unwrap();
214+
///
215+
/// // Pick a Serialize out of the values map.
216+
/// let value = values.get("vec").unwrap();
217+
///
218+
/// // This line prints `["a","b"]` to stdout.
219+
/// value.erased_serialize(format).unwrap();
220+
/// }
221+
/// ```
222+
pub fn erase<S>(serializer: S) -> impl Serializer [erase::Serializer<S>]
223+
where
224+
S: serde::Serializer,
225+
{
226+
erase::Serializer::new(serializer)
227+
}
226228
}
227229
}
228230

@@ -1609,4 +1611,11 @@ mod tests {
16091611
assert::<Vec<Box<dyn Serialize>>>();
16101612
assert::<Vec<Box<dyn Serialize + Send>>>();
16111613
}
1614+
1615+
#[test]
1616+
fn test_dangle() {
1617+
let mut json_serializer = serde_json::Serializer::new(Vec::new());
1618+
let _erased_serializer = <dyn Serializer>::erase(&mut json_serializer);
1619+
drop(json_serializer);
1620+
}
16121621
}

0 commit comments

Comments
 (0)