1
1
//! Managing and parsing resource
2
- use std:: collections:: HashMap ;
2
+ use std:: { cmp, collections:: HashMap , fmt} ;
3
+
4
+ use serde:: de:: { Deserialize , Deserializer , MapAccess , Visitor } ;
3
5
4
6
use crate :: websocket:: room_object_macros:: Updatable ;
5
7
@@ -202,7 +204,7 @@ impl ResourceType {
202
204
}
203
205
204
206
/// The resources and amounts of each resource some game object holds.
205
- #[ derive( Serialize , Deserialize , Clone , Debug , Default , PartialEq , Eq ) ]
207
+ #[ derive( Serialize , Clone , Debug , Default , PartialEq , Eq ) ]
206
208
#[ serde( transparent) ]
207
209
pub struct Store ( pub HashMap < ResourceType , i32 > ) ;
208
210
@@ -218,21 +220,110 @@ impl Store {
218
220
}
219
221
}
220
222
223
+ struct StoreVisitor ;
224
+
225
+ impl < ' de > Visitor < ' de > for StoreVisitor {
226
+ type Value = Store ;
227
+
228
+ fn expecting ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
229
+ f. write_str ( "a map" )
230
+ }
231
+
232
+ #[ inline]
233
+ fn visit_map < A > ( self , mut map : A ) -> Result < Self :: Value , A :: Error >
234
+ where
235
+ A : MapAccess < ' de > ,
236
+ {
237
+ // Adopted from `HashMap` `Deserialize` impl from
238
+ // https://github.com/serde-rs/serde/blob/master/serde/src/de/impls.rs
239
+ let mut values = HashMap :: with_capacity ( cmp:: min ( map. size_hint ( ) . unwrap_or ( 0 ) , 4096 ) ) ;
240
+
241
+ while let Some ( ( key, value) ) = map. next_entry :: < _ , Option < i32 > > ( ) ? {
242
+ let value = value. unwrap_or ( 0 ) ;
243
+ if value != 0 {
244
+ values. insert ( key, value) ;
245
+ }
246
+ }
247
+
248
+ Ok ( Store ( values) )
249
+ }
250
+ }
251
+
252
+ impl < ' de > Deserialize < ' de > for Store {
253
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
254
+ where
255
+ D : Deserializer < ' de > ,
256
+ {
257
+ deserializer. deserialize_map ( StoreVisitor )
258
+ }
259
+ }
260
+
261
+ /// Update structure for Store. The difference is that StoreUpdate allows 0 values.
262
+ #[ derive( Serialize , Clone , Debug , Default , PartialEq , Eq ) ]
263
+ #[ serde( transparent) ]
264
+ pub struct StoreUpdate ( pub HashMap < ResourceType , i32 > ) ;
265
+
266
+ /// Like `StoreVisitor`, but keeps 0s and nulls.
267
+ struct StoreUpdateVisitor ;
268
+
269
+ impl < ' de > Visitor < ' de > for StoreUpdateVisitor {
270
+ type Value = StoreUpdate ;
271
+
272
+ fn expecting ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
273
+ f. write_str ( "a map" )
274
+ }
275
+
276
+ #[ inline]
277
+ fn visit_map < A > ( self , mut map : A ) -> Result < Self :: Value , A :: Error >
278
+ where
279
+ A : MapAccess < ' de > ,
280
+ {
281
+ // Adopted from `HashMap` `Deserialize` impl from
282
+ // https://github.com/serde-rs/serde/blob/master/serde/src/de/impls.rs
283
+ let mut values = HashMap :: with_capacity ( cmp:: min ( map. size_hint ( ) . unwrap_or ( 0 ) , 4096 ) ) ;
284
+
285
+ while let Some ( ( key, value) ) = map. next_entry :: < _ , Option < i32 > > ( ) ? {
286
+ let value = value. unwrap_or ( 0 ) ;
287
+ values. insert ( key, value) ;
288
+ }
289
+
290
+ Ok ( StoreUpdate ( values) )
291
+ }
292
+ }
293
+
294
+ impl < ' de > Deserialize < ' de > for StoreUpdate {
295
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
296
+ where
297
+ D : Deserializer < ' de > ,
298
+ {
299
+ deserializer. deserialize_map ( StoreUpdateVisitor )
300
+ }
301
+ }
302
+
221
303
impl Updatable for Store {
222
304
type Update = Store ;
223
305
fn apply_update ( & mut self , update : Self :: Update ) {
224
- self . 0 . extend ( update. 0 ) ;
306
+ for ( key, value) in update. 0 {
307
+ if value == 0 {
308
+ self . 0 . remove ( & key) ;
309
+ } else {
310
+ self . 0 . insert ( key, value) ;
311
+ }
312
+ }
225
313
}
226
314
227
315
fn create_from_update ( update : Self :: Update ) -> Option < Self > {
228
- Some ( update)
316
+ let mut values = update. 0 ;
317
+ values. retain ( |_k, v| * v != 0 ) ;
318
+ Some ( Store ( values) )
229
319
}
230
320
}
231
321
232
322
#[ cfg( test) ]
233
323
macro_rules! store {
234
324
( $( $name: ident: $val: expr) ,* $( , ) ?) => (
235
325
{
326
+ #[ allow( unused_mut) ]
236
327
let mut store = crate :: websocket:: types:: room:: resources:: Store :: default ( ) ;
237
328
238
329
$(
0 commit comments