Skip to content

Commit fdc273f

Browse files
committed
Add specialization for reference-to-type
The serde library implements `Serialize` for all `&T where T: Serialize`. This causes min_specialization to select the default implementation of `Annotate` for `&T` when a specialized implementation exists for `T`. We supply a forwarding implementation for `&T` to `T` for every type we derive `Annotate` on. Signed-off-by: Chris Frantz <[email protected]>
1 parent 2c939e6 commit fdc273f

File tree

3 files changed

+56
-10
lines changed

3 files changed

+56
-10
lines changed

annotate_derive/src/expand.rs

+2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ fn impl_struct(input: Struct) -> TokenStream {
140140
// We don't have to implement `thunk_serialize` because the default implementation
141141
// already does what we need.
142142
}
143+
serde_annotate::annotate_ref!(#name);
143144
};
144145
}
145146
}
@@ -171,6 +172,7 @@ fn impl_enum(input: Enum) -> TokenStream {
171172
// We don't have to implement `thunk_serialize` because the default implementation
172173
// already does what we need.
173174
}
175+
serde_annotate::annotate_ref!(#name);
174176
};
175177
}
176178
}

src/annotate.rs

+30
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,36 @@ impl<T: ?Sized + serde::Serialize> Annotate for T {
6060
}
6161
}
6262

63+
// Serde explicitly implements Serialize on &T where T: Serialize. This
64+
// causes min_specialization to select the default implementation for &T
65+
// even though there is a specialized implementation available for T.
66+
//
67+
// The annotate_derive crate uses this macro to create the additional
68+
// specializations needed.
69+
#[macro_export]
70+
macro_rules! annotate_ref {
71+
($ty:ty) => {
72+
$crate::__annotate_ref!(&$ty);
73+
};
74+
}
75+
76+
#[macro_export]
77+
macro_rules! __annotate_ref {
78+
($ty:ty) => {
79+
impl Annotate for $ty {
80+
fn format(&self, variant: Option<&str>, field: &MemberId) -> Option<Format> {
81+
(**self).format(variant, field)
82+
}
83+
fn comment(&self, variant: Option<&str>, field: &MemberId) -> Option<String> {
84+
(**self).comment(variant, field)
85+
}
86+
fn as_annotate(&self) -> Option<&dyn Annotate> {
87+
(**self).as_annotate()
88+
}
89+
}
90+
};
91+
}
92+
6393
// We use a private trait to identify whether the Serializer passed to
6494
// various functions is our Serializer.
6595
pub(crate) unsafe trait IsSerializer {

tests/test_format.rs

+24-10
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,11 @@ struct Addresses {
275275
a: NesAddress,
276276
b: NesAddress,
277277
c: Option<NesAddress>,
278-
d: CpuAddress,
279-
e: NesAddress,
278+
// Note: using a vec here causes the serializer to request
279+
// serializing &CpuAddress rather than CpuAddress. This tests
280+
// that the specializations of Annotate for &T are working.
281+
vectors: Vec<CpuAddress>,
282+
inv: NesAddress,
280283
}
281284

282285
#[test]
@@ -285,8 +288,8 @@ fn test_nes_addresses() -> Result<()> {
285288
a: NesAddress::File(0x4010),
286289
b: NesAddress::Prg(1, 0x8000),
287290
c: Some(NesAddress::Chr(2, 0x400)),
288-
d: CpuAddress(0xFFFA),
289-
e: NesAddress::Invalid,
291+
vectors: vec![CpuAddress(0xFFFA), CpuAddress(0xFFFC), CpuAddress(0xFFFE)],
292+
inv: NesAddress::Invalid,
290293
};
291294

292295
tester!(
@@ -304,8 +307,12 @@ fn test_nes_addresses() -> Result<()> {
304307
"c": {
305308
"Chr": [2, 1024]
306309
},
307-
"d": 65530,
308-
"e": "Invalid"
310+
"vectors": [
311+
65530,
312+
65532,
313+
65534
314+
],
315+
"inv": "Invalid"
309316
}"#
310317
);
311318

@@ -327,8 +334,12 @@ fn test_nes_addresses() -> Result<()> {
327334
// NES CHR bank:address
328335
Chr: [0x2, 0x400]
329336
},
330-
d: 0xFFFA,
331-
e: "Invalid" // Bad Address
337+
vectors: [
338+
0xFFFA,
339+
0xFFFC,
340+
0xFFFE
341+
],
342+
inv: "Invalid" // Bad Address
332343
}"#
333344
);
334345

@@ -347,8 +358,11 @@ fn test_nes_addresses() -> Result<()> {
347358
c:
348359
# NES CHR bank:address
349360
Chr: [0x2, 0x400]
350-
d: 0xFFFA
351-
e: Invalid # Bad Address"#
361+
vectors:
362+
- 0xFFFA
363+
- 0xFFFC
364+
- 0xFFFE
365+
inv: Invalid # Bad Address"#
352366
);
353367

354368
Ok(())

0 commit comments

Comments
 (0)