Skip to content

Commit 02acd89

Browse files
committed
impl GcDeserialize for tuples and PhantomData
1 parent c3e6287 commit 02acd89

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

src/manually_traced/core.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ macro_rules! trace_tuple {
1717
{ $single_param:ident } => {
1818
trace_tuple_impl!();
1919
trace_tuple_impl!($single_param);
20+
#[cfg(feature = "serde1")]
21+
deser_tuple_impl!($single_param);
2022
};
2123
{ $first_param:ident, $($param:ident),* } => {
2224
trace_tuple! { $($param),* }
2325
trace_tuple_impl!( $first_param, $($param),*);
26+
#[cfg(feature = "serde1")]
27+
deser_tuple_impl!($first_param, $($param),*);
2428
};
2529
}
2630

@@ -104,6 +108,60 @@ macro_rules! trace_tuple_impl {
104108
};
105109
}
106110

111+
#[cfg(feature = "serde1")]
112+
macro_rules! deser_tuple_impl {
113+
( $($param:ident),+ ) => {
114+
115+
impl<'gc, 'de, Id: $crate::CollectorId, $($param),*> $crate::serde::GcDeserialize<'gc, 'de, Id> for ($($param,)*)
116+
where $($param: $crate::serde::GcDeserialize<'gc, 'de, Id>),* {
117+
#[allow(non_snake_case, unused)]
118+
fn deserialize_gc<Deser: serde::Deserializer<'de>>(
119+
ctx: &'gc <<Id as $crate::CollectorId>::System as $crate::GcSystem>::Context,
120+
deser: Deser
121+
) -> Result<Self, <Deser as serde::Deserializer<'de>>::Error> {
122+
use serde::de::{Visitor, Error, SeqAccess};
123+
use std::marker::PhantomData;
124+
use $crate::{CollectorId, GcSystem};
125+
struct TupleVisitor<'gc, 'de, Id: $crate::CollectorId, $($param: $crate::serde::GcDeserialize<'gc, 'de, Id>),*> {
126+
ctx: &'gc <Id::System as GcSystem>::Context,
127+
marker: PhantomData<(&'de (), ( $($param,)*) )>
128+
}
129+
impl<'gc, 'de, Id: CollectorId, $($param: $crate::serde::GcDeserialize<'gc, 'de, Id>),*>
130+
Visitor<'de> for TupleVisitor<'gc, 'de, Id, $($param),*> {
131+
type Value = ($($param,)*);
132+
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
133+
let mut count = 0;
134+
$(
135+
let $param = ();
136+
count += 1;
137+
)*
138+
write!(f, "a tuple of len {}", count)
139+
}
140+
fn visit_seq<SeqAcc: SeqAccess<'de>>(self, mut seq: SeqAcc) -> Result<Self::Value, SeqAcc::Error> {
141+
let mut idx = 0;
142+
$(
143+
let $param = match seq.next_element_seed($crate::serde::GcDeserializeSeed::new(self.ctx))? {
144+
Some(value) => value,
145+
None => return Err(Error::invalid_length(idx, &self))
146+
};
147+
idx += 1;
148+
)*
149+
Ok(($($param,)*))
150+
}
151+
}
152+
let mut len = 0;
153+
$(
154+
let _hack = PhantomData::<$param>;
155+
len += 1;
156+
)*
157+
Ok(deser.deserialize_tuple(len, TupleVisitor {
158+
marker: PhantomData, ctx
159+
})?)
160+
}
161+
}
162+
};
163+
}
164+
107165
unsafe_trace_primitive!(i8);
108166
unsafe_trace_primitive!(i16);
109167
unsafe_trace_primitive!(i32);

src/serde.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
use std::marker::PhantomData;
1313

1414
use crate::array::{GcArray, GcString};
15-
use serde::{Serialize, de::{self, Deserializer, DeserializeSeed}, ser::SerializeSeq};
15+
use indexmap::set::Union;
16+
use serde::{Serialize, de::{self, Deserializer, Visitor, DeserializeSeed}, ser::SerializeSeq};
1617

1718
use crate::prelude::*;
1819

@@ -93,6 +94,35 @@ impl<'gc, Id: CollectorId> Serialize for GcString<'gc, Id> {
9394
}
9495
}
9596

97+
/*
98+
* impl GcDeserialize for PhantomData<T>
99+
* regardless of T
100+
* NOTE: We still need T: 'gc because of GcSafe bound....
101+
* TODO: Remove this if and when T: GcSafe becomes independent of T: 'gc
102+
*/
103+
impl<'gc, 'de, T: 'gc, Id: CollectorId> GcDeserialize<'gc, 'de, Id> for PhantomData<T> {
104+
fn deserialize_gc<D: Deserializer<'de>>(_ctx: &'gc <Id::System as GcSystem>::Context, _deserializer: D) -> Result<Self, D::Error> {
105+
Ok(PhantomData)
106+
}
107+
}
108+
109+
impl<'gc, 'de, Id: CollectorId> GcDeserialize<'gc, 'de, Id> for () {
110+
fn deserialize_gc<D: Deserializer<'de>>(_ctx: &'gc <Id::System as GcSystem>::Context, deserializer: D) -> Result<Self, D::Error> {
111+
112+
struct UnitVisitor;
113+
impl<'de> Visitor<'de> for UnitVisitor {
114+
type Value = ();
115+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
116+
formatter.write_str("a unit tuple")
117+
}
118+
fn visit_unit<E>(self) -> Result<Self::Value, E> where
119+
E: de::Error, {
120+
Ok(())
121+
}
122+
}
123+
deserializer.deserialize_unit(UnitVisitor)
124+
}
125+
}
96126

97127
/// Implement [GcDeserialize] for a type by delegating to its [serde::Deserialize] implementation.
98128
///

0 commit comments

Comments
 (0)