5
5
//! should go in this module.
6
6
use std:: collections:: { HashMap , HashSet } ;
7
7
#[ cfg( feature = "serde1" ) ]
8
- use std:: hash:: Hash ;
8
+ use std:: hash:: { Hash , BuildHasher } ;
9
+ #[ cfg( feature = "serde1" ) ]
10
+ use std:: marker:: PhantomData ;
9
11
10
12
use zerogc_derive:: unsafe_gc_impl;
11
13
@@ -15,12 +17,20 @@ use crate::prelude::*;
15
17
16
18
17
19
unsafe_gc_impl ! {
18
- target => HashMap <K , V >,
19
- params => [ K : TraceImmutable , V ] ,
20
+ target => HashMap <K , V , S >,
21
+ params => [ K : TraceImmutable , V , S : ' static ] ,
20
22
bounds => {
21
- GcDeserialize => { where K : GcDeserialize <' gc, ' deserialize, Id > + Eq + Hash , V : GcDeserialize <' gc, ' deserialize, Id > }
23
+ /*
24
+ * We require S: 'static so that we know S: NullTrace
25
+ */
26
+ Trace => { where K : TraceImmutable , V : Trace , S : ' static } ,
27
+ TraceImmutable => { where K : TraceImmutable , V : TraceImmutable , S : ' static } ,
28
+ TrustedDrop => { where K : TrustedDrop , V : TrustedDrop , S : ' static } ,
29
+ GcSafe => { where K : TraceImmutable + GcSafe <' gc, Id >, V : GcSafe <' gc, Id >, S : ' static } ,
30
+ GcDeserialize => { where K : GcDeserialize <' gc, ' deserialize, Id > + Eq + Hash ,
31
+ V : GcDeserialize <' gc, ' deserialize, Id >, S : Default + BuildHasher }
22
32
} ,
23
- null_trace => { where K : NullTrace , V : NullTrace } ,
33
+ null_trace => { where K : NullTrace , V : NullTrace , S : NullTrace } ,
24
34
NEEDS_TRACE => K :: NEEDS_TRACE || V :: NEEDS_TRACE ,
25
35
NEEDS_DROP => true , // Internal memory
26
36
collector_id => * ,
@@ -29,27 +39,113 @@ unsafe_gc_impl! {
29
39
visitor. visit_immutable:: <K >( key) ?;
30
40
visitor. #visit_func:: <V >( value) ?;
31
41
}
42
+ // NOTE: Because S: 'static, we can assume S: NullTrace
32
43
Ok ( ( ) )
33
44
} ,
34
- deserialize => unstable_horrible_hack,
45
+ deserialize => |ctx, deserializer| {
46
+ use serde:: de:: { Visitor , MapAccess } ;
47
+ use crate :: serde:: GcDeserializeSeed ;
48
+ struct MapVisitor <
49
+ ' gc, ' de, Id : CollectorId ,
50
+ K : GcDeserialize <' gc, ' de, Id >,
51
+ V : GcDeserialize <' gc, ' de, Id >,
52
+ S : BuildHasher + Default
53
+ > {
54
+ ctx: & ' gc <Id :: System as GcSystem >:: Context ,
55
+ marker: PhantomData <fn ( & ' de ( ) , S ) -> ( K , V ) >
56
+ }
57
+ impl <' gc, ' de, Id : CollectorId ,
58
+ K : Eq + Hash + GcDeserialize <' gc, ' de, Id >,
59
+ V : GcDeserialize <' gc, ' de, Id >,
60
+ S : BuildHasher + Default
61
+ > Visitor <' de> for MapVisitor <' gc, ' de, Id , K , V , S > {
62
+ type Value = HashMap <K , V , S >;
63
+ fn expecting( & self , f: & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
64
+ f. write_str( "a map" )
65
+ }
66
+ #[ inline]
67
+ fn visit_map<A >( self , mut access: A ) -> Result <Self :: Value , A :: Error >
68
+ where A : MapAccess <' de>, {
69
+ let mut values = HashMap :: <K , V , S >:: with_capacity_and_hasher(
70
+ access. size_hint( ) . unwrap_or( 0 ) . min( 1024 ) ,
71
+ S :: default ( )
72
+ ) ;
73
+ while let Some ( ( key, value) ) = access. next_entry_seed(
74
+ GcDeserializeSeed :: new( self . ctx) ,
75
+ GcDeserializeSeed :: new( self . ctx)
76
+ ) ? {
77
+ values. insert( key, value) ;
78
+ }
79
+
80
+ Ok ( values)
81
+ }
82
+ }
83
+ let visitor: MapVisitor <Id , K , V , S > = MapVisitor { ctx, marker: PhantomData } ;
84
+ deserializer. deserialize_map( visitor)
85
+ } ,
35
86
}
36
87
37
88
38
89
unsafe_gc_impl ! {
39
- target => HashSet <T >,
40
- params => [ T : TraceImmutable ] ,
90
+ target => HashSet <T , S >,
91
+ params => [ T : TraceImmutable , S : ' static ] ,
41
92
bounds => {
42
- GcDeserialize => { where T : GcDeserialize <' gc, ' deserialize, Id > + Eq + Hash }
93
+ /*
94
+ * We require S: 'static so that we know S: NullTrace
95
+ */
96
+ Trace => { where T : TraceImmutable , S : ' static } ,
97
+ TraceImmutable => { where T : TraceImmutable , S : ' static } ,
98
+ TrustedDrop => { where T : TrustedDrop , S : ' static } ,
99
+ GcSafe => { where T : TraceImmutable + GcSafe <' gc, Id >, S : ' static } ,
100
+ GcDeserialize => { where T : GcDeserialize <' gc, ' deserialize, Id > + Eq + Hash , S : BuildHasher + Default }
43
101
} ,
44
- null_trace => { where T : NullTrace } ,
102
+ null_trace => { where T : NullTrace , S : ' static } ,
45
103
NEEDS_TRACE => T :: NEEDS_TRACE ,
46
104
NEEDS_DROP => true , // Internal memory
47
105
collector_id => * ,
48
106
visit => |self , visitor| {
49
107
for val in self . iter( ) {
50
108
visitor. visit_immutable:: <T >( val) ?;
51
- }
109
+ }
110
+ // NOTE: Because S: 'static, we can assume S: NullTrace
52
111
Ok ( ( ) )
53
112
} ,
54
- deserialize => unstable_horrible_hack,
113
+ deserialize => |ctx, deserializer| {
114
+ use serde:: de:: { Visitor , SeqAccess } ;
115
+ use crate :: serde:: GcDeserializeSeed ;
116
+ struct SetVisitor <
117
+ ' gc, ' de, Id : CollectorId ,
118
+ T : GcDeserialize <' gc, ' de, Id >,
119
+ S : BuildHasher + Default
120
+ > {
121
+ ctx: & ' gc <Id :: System as GcSystem >:: Context ,
122
+ marker: PhantomData <fn ( & ' de ( ) , S ) -> T >
123
+ }
124
+ impl <' gc, ' de, Id : CollectorId ,
125
+ T : Eq + Hash + GcDeserialize <' gc, ' de, Id >,
126
+ S : BuildHasher + Default
127
+ > Visitor <' de> for SetVisitor <' gc, ' de, Id , T , S > {
128
+ type Value = HashSet <T , S >;
129
+ fn expecting( & self , f: & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
130
+ f. write_str( "a set" )
131
+ }
132
+ #[ inline]
133
+ fn visit_seq<A >( self , mut access: A ) -> Result <Self :: Value , A :: Error >
134
+ where A : SeqAccess <' de>, {
135
+ let mut values = HashSet :: <T , S >:: with_capacity_and_hasher(
136
+ access. size_hint( ) . unwrap_or( 0 ) . min( 1024 ) ,
137
+ S :: default ( )
138
+ ) ;
139
+ while let Some ( value) = access. next_element_seed(
140
+ GcDeserializeSeed :: new( self . ctx)
141
+ ) ? {
142
+ values. insert( value) ;
143
+ }
144
+
145
+ Ok ( values)
146
+ }
147
+ }
148
+ let visitor: SetVisitor <Id , T , S > = SetVisitor { ctx, marker: PhantomData } ;
149
+ deserializer. deserialize_seq( visitor)
150
+ } ,
55
151
}
0 commit comments