platform_value/btreemap_extensions/
btreemap_removal_extensions.rs

1use crate::{BinaryData, Bytes20, Bytes32, Error, Identifier, Value};
2use std::collections::BTreeMap;
3
4pub trait BTreeValueRemoveFromMapHelper {
5    fn remove_optional_string(&mut self, key: &str) -> Result<Option<String>, Error>;
6    fn remove_string(&mut self, key: &str) -> Result<String, Error>;
7    fn remove_optional_float(&mut self, key: &str) -> Result<Option<f64>, Error>;
8    fn remove_float(&mut self, key: &str) -> Result<f64, Error>;
9    fn remove_optional_integer<T>(&mut self, key: &str) -> Result<Option<T>, Error>
10    where
11        T: TryFrom<i128>
12            + TryFrom<u128>
13            + TryFrom<u64>
14            + TryFrom<i64>
15            + TryFrom<u32>
16            + TryFrom<i32>
17            + TryFrom<u16>
18            + TryFrom<i16>
19            + TryFrom<u8>
20            + TryFrom<i8>;
21    fn remove_integer<T>(&mut self, key: &str) -> Result<T, Error>
22    where
23        T: TryFrom<i128>
24            + TryFrom<u128>
25            + TryFrom<u64>
26            + TryFrom<i64>
27            + TryFrom<u32>
28            + TryFrom<i32>
29            + TryFrom<u16>
30            + TryFrom<i16>
31            + TryFrom<u8>
32            + TryFrom<i8>;
33    fn remove_optional_hash256_bytes(&mut self, key: &str) -> Result<Option<[u8; 32]>, Error>;
34    fn remove_hash256_bytes(&mut self, key: &str) -> Result<[u8; 32], Error>;
35    fn remove_optional_bytes(&mut self, key: &str) -> Result<Option<Vec<u8>>, Error>;
36    fn remove_bytes(&mut self, key: &str) -> Result<Vec<u8>, Error>;
37    fn remove_optional_bool(&mut self, key: &str) -> Result<Option<bool>, Error>;
38    fn remove_bool(&mut self, key: &str) -> Result<bool, Error>;
39    fn remove_optional_identifier(&mut self, key: &str) -> Result<Option<Identifier>, Error>;
40    fn remove_identifier(&mut self, key: &str) -> Result<Identifier, Error>;
41    fn remove_binary_data(&mut self, key: &str) -> Result<BinaryData, Error>;
42    fn remove_optional_binary_data(&mut self, key: &str) -> Result<Option<BinaryData>, Error>;
43    fn remove_optional_bytes_32(&mut self, key: &str) -> Result<Option<Bytes32>, Error>;
44    fn remove_bytes_32(&mut self, key: &str) -> Result<Bytes32, Error>;
45    fn remove_optional_bytes_20(&mut self, key: &str) -> Result<Option<Bytes20>, Error>;
46    fn remove_bytes_20(&mut self, key: &str) -> Result<Bytes20, Error>;
47    fn remove_optional_hash256s(&mut self, key: &str) -> Result<Option<Vec<[u8; 32]>>, Error>;
48    fn remove_hash256s(&mut self, key: &str) -> Result<Vec<[u8; 32]>, Error>;
49    fn remove_identifiers(&mut self, key: &str) -> Result<Vec<Identifier>, Error>;
50    fn remove_optional_identifiers(&mut self, key: &str) -> Result<Option<Vec<Identifier>>, Error>;
51    fn remove_map_as_btree_map<K, V>(&mut self, key: &str) -> Result<BTreeMap<K, V>, Error>
52    where
53        K: TryFrom<Value, Error = Error> + Ord,
54        V: TryFrom<Value, Error = Error>;
55    fn remove_optional_map_as_btree_map<K, V>(
56        &mut self,
57        key: &str,
58    ) -> Result<Option<BTreeMap<K, V>>, Error>
59    where
60        K: TryFrom<Value, Error = Error> + Ord,
61        V: TryFrom<Value, Error = Error>;
62
63    fn remove_map_as_btree_map_keep_values_as_platform_value<K, V>(
64        &mut self,
65        key: &str,
66    ) -> Result<BTreeMap<K, Value>, Error>
67    where
68        K: TryFrom<Value, Error = Error> + Ord;
69
70    fn remove_optional_map_as_btree_map_keep_values_as_platform_value<K>(
71        &mut self,
72        key: &str,
73    ) -> Result<Option<BTreeMap<K, Value>>, Error>
74    where
75        K: TryFrom<Value, Error = Error> + Ord;
76}
77
78pub trait BTreeValueRemoveTupleFromMapHelper {
79    fn remove_tuple<K, V>(&mut self, key: &str) -> Result<(K, V), Error>
80    where
81        K: TryFrom<Value, Error = Error> + Ord,
82        V: TryFrom<Value, Error = Error>;
83    fn remove_optional_tuple<K, V>(&mut self, key: &str) -> Result<Option<(K, V)>, Error>
84    where
85        K: TryFrom<Value, Error = Error> + Ord,
86        V: TryFrom<Value, Error = Error>;
87}
88
89impl BTreeValueRemoveFromMapHelper for BTreeMap<String, &Value> {
90    fn remove_optional_string(&mut self, key: &str) -> Result<Option<String>, Error> {
91        self.remove(key)
92            .and_then(|v| if v.is_null() { None } else { Some(v.to_text()) })
93            .transpose()
94    }
95
96    fn remove_string(&mut self, key: &str) -> Result<String, Error> {
97        self.remove_optional_string(key)?
98            .ok_or_else(|| Error::StructureError(format!("unable to remove string property {key}")))
99    }
100
101    fn remove_optional_float(&mut self, key: &str) -> Result<Option<f64>, Error> {
102        self.remove(key)
103            .and_then(|v| {
104                if v.is_null() {
105                    None
106                } else {
107                    Some(v.to_float())
108                }
109            })
110            .transpose()
111    }
112
113    fn remove_float(&mut self, key: &str) -> Result<f64, Error> {
114        self.remove_optional_float(key)?
115            .ok_or_else(|| Error::StructureError(format!("unable to remove float property {key}")))
116    }
117
118    fn remove_optional_integer<T>(&mut self, key: &str) -> Result<Option<T>, Error>
119    where
120        T: TryFrom<i128>
121            + TryFrom<u128>
122            + TryFrom<u64>
123            + TryFrom<i64>
124            + TryFrom<u32>
125            + TryFrom<i32>
126            + TryFrom<u16>
127            + TryFrom<i16>
128            + TryFrom<u8>
129            + TryFrom<i8>,
130    {
131        self.remove(key)
132            .and_then(|v| {
133                if v.is_null() {
134                    None
135                } else {
136                    Some(v.to_integer())
137                }
138            })
139            .transpose()
140    }
141
142    fn remove_integer<T>(&mut self, key: &str) -> Result<T, Error>
143    where
144        T: TryFrom<i128>
145            + TryFrom<u128>
146            + TryFrom<u64>
147            + TryFrom<i64>
148            + TryFrom<u32>
149            + TryFrom<i32>
150            + TryFrom<u16>
151            + TryFrom<i16>
152            + TryFrom<u8>
153            + TryFrom<i8>,
154    {
155        self.remove_optional_integer(key)?.ok_or_else(|| {
156            Error::StructureError(format!("unable to remove integer property {key}"))
157        })
158    }
159
160    fn remove_optional_hash256_bytes(&mut self, key: &str) -> Result<Option<[u8; 32]>, Error> {
161        self.remove(key)
162            .and_then(|v| {
163                if v.is_null() {
164                    None
165                } else {
166                    Some(v.to_hash256())
167                }
168            })
169            .transpose()
170    }
171
172    fn remove_hash256_bytes(&mut self, key: &str) -> Result<[u8; 32], Error> {
173        self.remove_optional_hash256_bytes(key)?.ok_or_else(|| {
174            Error::StructureError(format!("unable to remove hash256 property {key}"))
175        })
176    }
177
178    fn remove_optional_bytes(&mut self, key: &str) -> Result<Option<Vec<u8>>, Error> {
179        self.remove(key)
180            .and_then(|v| {
181                if v.is_null() {
182                    None
183                } else {
184                    Some(v.to_identifier_bytes())
185                }
186            })
187            .transpose()
188    }
189
190    fn remove_bytes(&mut self, key: &str) -> Result<Vec<u8>, Error> {
191        self.remove_optional_bytes(key)?
192            .ok_or_else(|| Error::StructureError(format!("unable to remove bytes property {key}")))
193    }
194
195    fn remove_optional_bool(&mut self, key: &str) -> Result<Option<bool>, Error> {
196        self.remove(key)
197            .and_then(|v| if v.is_null() { None } else { Some(v.to_bool()) })
198            .transpose()
199    }
200
201    fn remove_bool(&mut self, key: &str) -> Result<bool, Error> {
202        self.remove_optional_bool(key)?
203            .ok_or_else(|| Error::StructureError(format!("unable to remove float property {key}")))
204    }
205
206    fn remove_optional_identifier(&mut self, key: &str) -> Result<Option<Identifier>, Error> {
207        self.remove(key)
208            .and_then(|v| {
209                if v.is_null() {
210                    None
211                } else {
212                    Some(v.to_identifier())
213                }
214            })
215            .transpose()
216    }
217
218    fn remove_identifier(&mut self, key: &str) -> Result<Identifier, Error> {
219        self.remove_optional_identifier(key)?.ok_or_else(|| {
220            Error::StructureError(format!("unable to remove identifier property {key}"))
221        })
222    }
223
224    fn remove_binary_data(&mut self, key: &str) -> Result<BinaryData, Error> {
225        self.remove_optional_binary_data(key)?.ok_or_else(|| {
226            Error::StructureError(format!("unable to remove binary data property {key}"))
227        })
228    }
229
230    fn remove_optional_binary_data(&mut self, key: &str) -> Result<Option<BinaryData>, Error> {
231        self.remove(key)
232            .and_then(|v| {
233                if v.is_null() {
234                    None
235                } else {
236                    Some(v.to_binary_data())
237                }
238            })
239            .transpose()
240    }
241
242    fn remove_optional_bytes_32(&mut self, key: &str) -> Result<Option<Bytes32>, Error> {
243        self.remove(key)
244            .and_then(|v| {
245                if v.is_null() {
246                    None
247                } else {
248                    Some(v.to_bytes_32())
249                }
250            })
251            .transpose()
252    }
253
254    fn remove_bytes_32(&mut self, key: &str) -> Result<Bytes32, Error> {
255        self.remove_optional_bytes_32(key)?.ok_or_else(|| {
256            Error::StructureError(format!("unable to remove binary 32 bytes property {key}"))
257        })
258    }
259
260    fn remove_optional_bytes_20(&mut self, key: &str) -> Result<Option<Bytes20>, Error> {
261        self.remove(key)
262            .and_then(|v| {
263                if v.is_null() {
264                    None
265                } else {
266                    Some(v.to_bytes_20())
267                }
268            })
269            .transpose()
270    }
271
272    fn remove_bytes_20(&mut self, key: &str) -> Result<Bytes20, Error> {
273        self.remove_optional_bytes_20(key)?.ok_or_else(|| {
274            Error::StructureError(format!("unable to remove binary bytes 20 property {key}"))
275        })
276    }
277
278    fn remove_optional_hash256s(&mut self, key: &str) -> Result<Option<Vec<[u8; 32]>>, Error> {
279        self.remove(key)
280            .and_then(|v| {
281                if v.is_null() {
282                    None
283                } else if let Value::Array(array) = v {
284                    Some(
285                        array
286                            .iter()
287                            .map(|item| item.clone().into_hash256())
288                            .collect(),
289                    )
290                } else {
291                    None
292                }
293            })
294            .transpose()
295    }
296
297    fn remove_hash256s(&mut self, key: &str) -> Result<Vec<[u8; 32]>, Error> {
298        self.remove_optional_hash256s(key)?.ok_or_else(|| {
299            Error::StructureError(format!("unable to remove identifier property {key}"))
300        })
301    }
302
303    fn remove_identifiers(&mut self, key: &str) -> Result<Vec<Identifier>, Error> {
304        self.remove_optional_identifiers(key)?.ok_or_else(|| {
305            Error::StructureError(format!("unable to remove identifier property {key}"))
306        })
307    }
308
309    fn remove_optional_identifiers(&mut self, key: &str) -> Result<Option<Vec<Identifier>>, Error> {
310        self.remove(key)
311            .and_then(|v| {
312                if v.is_null() {
313                    None
314                } else if let Value::Array(array) = v {
315                    Some(array.iter().map(|item| item.to_identifier()).collect())
316                } else {
317                    None
318                }
319            })
320            .transpose()
321    }
322
323    fn remove_map_as_btree_map<K, V>(&mut self, key: &str) -> Result<BTreeMap<K, V>, Error>
324    where
325        K: TryFrom<Value, Error = Error> + Ord,
326        V: TryFrom<Value, Error = Error>,
327    {
328        self.remove_optional_map_as_btree_map(key)?
329            .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}")))
330    }
331
332    fn remove_optional_map_as_btree_map<K, V>(
333        &mut self,
334        key: &str,
335    ) -> Result<Option<BTreeMap<K, V>>, Error>
336    where
337        K: TryFrom<Value, Error = Error> + Ord,
338        V: TryFrom<Value, Error = Error>,
339    {
340        self.remove(key)
341            .and_then(|v| {
342                if v.is_null() {
343                    None
344                } else if let Value::Map(map) = v {
345                    Some(
346                        map.iter()
347                            .map(|(key, value)| {
348                                Ok((key.clone().try_into()?, value.clone().try_into()?))
349                            })
350                            .collect(),
351                    )
352                } else {
353                    None
354                }
355            })
356            .transpose()
357    }
358
359    fn remove_map_as_btree_map_keep_values_as_platform_value<K, V>(
360        &mut self,
361        key: &str,
362    ) -> Result<BTreeMap<K, Value>, Error>
363    where
364        K: TryFrom<Value, Error = Error> + Ord,
365    {
366        self.remove_optional_map_as_btree_map_keep_values_as_platform_value(key)?
367            .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}")))
368    }
369
370    fn remove_optional_map_as_btree_map_keep_values_as_platform_value<K>(
371        &mut self,
372        key: &str,
373    ) -> Result<Option<BTreeMap<K, Value>>, Error>
374    where
375        K: TryFrom<Value, Error = Error> + Ord,
376    {
377        self.remove(key)
378            .and_then(|v| {
379                if v.is_null() {
380                    None
381                } else if let Value::Map(map) = v {
382                    Some(
383                        map.iter()
384                            .map(|(key, value)| Ok((key.clone().try_into()?, value.clone())))
385                            .collect(),
386                    )
387                } else {
388                    None
389                }
390            })
391            .transpose()
392    }
393}
394
395impl BTreeValueRemoveFromMapHelper for BTreeMap<String, Value> {
396    fn remove_optional_string(&mut self, key: &str) -> Result<Option<String>, Error> {
397        self.remove(key)
398            .and_then(|v| {
399                if v.is_null() {
400                    None
401                } else {
402                    Some(v.into_text())
403                }
404            })
405            .transpose()
406    }
407
408    fn remove_string(&mut self, key: &str) -> Result<String, Error> {
409        self.remove_optional_string(key)?
410            .ok_or_else(|| Error::StructureError(format!("unable to remove string property {key}")))
411    }
412
413    fn remove_optional_float(&mut self, key: &str) -> Result<Option<f64>, Error> {
414        self.remove(key)
415            .and_then(|v| {
416                if v.is_null() {
417                    None
418                } else {
419                    Some(v.into_float())
420                }
421            })
422            .transpose()
423    }
424
425    fn remove_float(&mut self, key: &str) -> Result<f64, Error> {
426        self.remove_optional_float(key)?
427            .ok_or_else(|| Error::StructureError(format!("unable to remove float property {key}")))
428    }
429
430    fn remove_optional_integer<T>(&mut self, key: &str) -> Result<Option<T>, Error>
431    where
432        T: TryFrom<i128>
433            + TryFrom<u128>
434            + TryFrom<u64>
435            + TryFrom<i64>
436            + TryFrom<u32>
437            + TryFrom<i32>
438            + TryFrom<u16>
439            + TryFrom<i16>
440            + TryFrom<u8>
441            + TryFrom<i8>,
442    {
443        self.remove(key)
444            .and_then(|v| {
445                if v.is_null() {
446                    None
447                } else {
448                    Some(v.into_integer())
449                }
450            })
451            .transpose()
452    }
453
454    fn remove_integer<T>(&mut self, key: &str) -> Result<T, Error>
455    where
456        T: TryFrom<i128>
457            + TryFrom<u128>
458            + TryFrom<u64>
459            + TryFrom<i64>
460            + TryFrom<u32>
461            + TryFrom<i32>
462            + TryFrom<u16>
463            + TryFrom<i16>
464            + TryFrom<u8>
465            + TryFrom<i8>,
466    {
467        self.remove_optional_integer(key)?.ok_or_else(|| {
468            Error::StructureError(format!("unable to remove integer property {key}"))
469        })
470    }
471
472    fn remove_optional_hash256_bytes(&mut self, key: &str) -> Result<Option<[u8; 32]>, Error> {
473        self.remove(key)
474            .and_then(|v| {
475                if v.is_null() {
476                    None
477                } else {
478                    Some(v.into_hash256())
479                }
480            })
481            .transpose()
482    }
483
484    fn remove_hash256_bytes(&mut self, key: &str) -> Result<[u8; 32], Error> {
485        self.remove_optional_hash256_bytes(key)?.ok_or_else(|| {
486            Error::StructureError(format!("unable to remove hash256 property {key}"))
487        })
488    }
489
490    fn remove_optional_bytes(&mut self, key: &str) -> Result<Option<Vec<u8>>, Error> {
491        self.remove(key)
492            .and_then(|v| {
493                if v.is_null() {
494                    None
495                } else {
496                    Some(v.into_identifier_bytes())
497                }
498            })
499            .transpose()
500    }
501
502    fn remove_bytes(&mut self, key: &str) -> Result<Vec<u8>, Error> {
503        self.remove_optional_bytes(key)?
504            .ok_or_else(|| Error::StructureError(format!("unable to remove bytes property {key}")))
505    }
506
507    fn remove_optional_bool(&mut self, key: &str) -> Result<Option<bool>, Error> {
508        self.remove(key)
509            .and_then(|v| {
510                if v.is_null() {
511                    None
512                } else {
513                    Some(v.into_bool())
514                }
515            })
516            .transpose()
517    }
518
519    fn remove_bool(&mut self, key: &str) -> Result<bool, Error> {
520        self.remove_optional_bool(key)?
521            .ok_or_else(|| Error::StructureError(format!("unable to remove float property {key}")))
522    }
523
524    fn remove_optional_identifier(&mut self, key: &str) -> Result<Option<Identifier>, Error> {
525        self.remove(key)
526            .and_then(|v| {
527                if v.is_null() {
528                    None
529                } else {
530                    Some(v.into_identifier())
531                }
532            })
533            .transpose()
534    }
535
536    fn remove_identifier(&mut self, key: &str) -> Result<Identifier, Error> {
537        self.remove_optional_identifier(key)?.ok_or_else(|| {
538            Error::StructureError(format!("unable to remove identifier property {key}"))
539        })
540    }
541
542    fn remove_binary_data(&mut self, key: &str) -> Result<BinaryData, Error> {
543        self.remove_optional_binary_data(key)?
544            .ok_or_else(|| Error::StructureError(format!("unable to remove bytes property {key}")))
545    }
546
547    fn remove_optional_binary_data(&mut self, key: &str) -> Result<Option<BinaryData>, Error> {
548        self.remove(key)
549            .and_then(|v| {
550                if v.is_null() {
551                    None
552                } else {
553                    Some(v.into_binary_data())
554                }
555            })
556            .transpose()
557    }
558
559    fn remove_optional_bytes_32(&mut self, key: &str) -> Result<Option<Bytes32>, Error> {
560        self.remove(key)
561            .and_then(|v| {
562                if v.is_null() {
563                    None
564                } else {
565                    Some(v.into_bytes_32())
566                }
567            })
568            .transpose()
569    }
570
571    fn remove_bytes_32(&mut self, key: &str) -> Result<Bytes32, Error> {
572        self.remove_optional_bytes_32(key)?.ok_or_else(|| {
573            Error::StructureError(format!("unable to remove binary bytes 32 property {key}"))
574        })
575    }
576
577    fn remove_optional_bytes_20(&mut self, key: &str) -> Result<Option<Bytes20>, Error> {
578        self.remove(key)
579            .and_then(|v| {
580                if v.is_null() {
581                    None
582                } else {
583                    Some(v.into_bytes_20())
584                }
585            })
586            .transpose()
587    }
588
589    fn remove_bytes_20(&mut self, key: &str) -> Result<Bytes20, Error> {
590        self.remove_optional_bytes_20(key)?.ok_or_else(|| {
591            Error::StructureError(format!("unable to remove binary bytes 20 property {key}"))
592        })
593    }
594
595    fn remove_optional_hash256s(&mut self, key: &str) -> Result<Option<Vec<[u8; 32]>>, Error> {
596        self.remove(key)
597            .and_then(|v| {
598                if v.is_null() {
599                    None
600                } else if let Value::Array(array) = v {
601                    Some(array.into_iter().map(|item| item.into_hash256()).collect())
602                } else {
603                    None
604                }
605            })
606            .transpose()
607    }
608
609    fn remove_hash256s(&mut self, key: &str) -> Result<Vec<[u8; 32]>, Error> {
610        self.remove_optional_hash256s(key)?.ok_or_else(|| {
611            Error::StructureError(format!("unable to remove identifier property {key}"))
612        })
613    }
614
615    fn remove_identifiers(&mut self, key: &str) -> Result<Vec<Identifier>, Error> {
616        self.remove_optional_identifiers(key)?.ok_or_else(|| {
617            Error::StructureError(format!("unable to remove identifier property {key}"))
618        })
619    }
620
621    fn remove_optional_identifiers(&mut self, key: &str) -> Result<Option<Vec<Identifier>>, Error> {
622        self.remove(key)
623            .and_then(|v| {
624                if v.is_null() {
625                    None
626                } else if let Value::Array(array) = v {
627                    Some(
628                        array
629                            .into_iter()
630                            .map(|item| item.into_identifier())
631                            .collect(),
632                    )
633                } else {
634                    None
635                }
636            })
637            .transpose()
638    }
639
640    fn remove_map_as_btree_map<K, V>(&mut self, key: &str) -> Result<BTreeMap<K, V>, Error>
641    where
642        K: TryFrom<Value, Error = Error> + Ord,
643        V: TryFrom<Value, Error = Error>,
644    {
645        self.remove_optional_map_as_btree_map(key)?
646            .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}")))
647    }
648
649    fn remove_optional_map_as_btree_map<K, V>(
650        &mut self,
651        key: &str,
652    ) -> Result<Option<BTreeMap<K, V>>, Error>
653    where
654        K: TryFrom<Value, Error = Error> + Ord,
655        V: TryFrom<Value, Error = Error>,
656    {
657        self.remove(key)
658            .and_then(|v| {
659                if v.is_null() {
660                    None
661                } else if let Value::Map(map) = v {
662                    Some(
663                        map.into_iter()
664                            .map(|(key, value)| Ok((key.try_into()?, value.try_into()?)))
665                            .collect(),
666                    )
667                } else {
668                    None
669                }
670            })
671            .transpose()
672    }
673
674    fn remove_map_as_btree_map_keep_values_as_platform_value<K, V>(
675        &mut self,
676        key: &str,
677    ) -> Result<BTreeMap<K, Value>, Error>
678    where
679        K: TryFrom<Value, Error = Error> + Ord,
680    {
681        self.remove_optional_map_as_btree_map_keep_values_as_platform_value(key)?
682            .ok_or_else(|| Error::StructureError(format!("unable to remove map property {key}")))
683    }
684
685    fn remove_optional_map_as_btree_map_keep_values_as_platform_value<K>(
686        &mut self,
687        key: &str,
688    ) -> Result<Option<BTreeMap<K, Value>>, Error>
689    where
690        K: TryFrom<Value, Error = Error> + Ord,
691    {
692        self.remove(key)
693            .and_then(|v| {
694                if v.is_null() {
695                    None
696                } else if let Value::Map(map) = v {
697                    Some(
698                        map.into_iter()
699                            .map(|(key, value)| Ok((key.try_into()?, value)))
700                            .collect(),
701                    )
702                } else {
703                    None
704                }
705            })
706            .transpose()
707    }
708}
709
710impl BTreeValueRemoveTupleFromMapHelper for BTreeMap<String, Value> {
711    fn remove_tuple<K, V>(&mut self, key: &str) -> Result<(K, V), Error>
712    where
713        K: TryFrom<Value, Error = Error> + Ord,
714        V: TryFrom<Value, Error = Error>,
715    {
716        self.remove_optional_tuple(key)?
717            .ok_or_else(|| Error::StructureError(format!("unable to remove tuple property {key}")))
718    }
719
720    fn remove_optional_tuple<K, V>(&mut self, key: &str) -> Result<Option<(K, V)>, Error>
721    where
722        K: TryFrom<Value, Error = Error> + Ord,
723        V: TryFrom<Value, Error = Error>,
724    {
725        self.remove(key)
726            .and_then(|v| {
727                if v.is_null() {
728                    None
729                } else if let Value::Array(mut arr) = v {
730                    if arr.len() == 2 {
731                        let key_value = match arr.remove(0).try_into() {
732                            Ok(key_value) => key_value,
733                            Err(e) => return Some(Err(e)),
734                        };
735                        // After removing index 0 above, the second element is now at index 0
736                        let value_value: V = match arr.remove(0).try_into() {
737                            Ok(key_value) => key_value,
738                            Err(e) => return Some(Err(e)),
739                        };
740                        Some(Ok((key_value, value_value)))
741                    } else {
742                        Some(Err(Error::StructureError(format!(
743                            "Value for key {key} is not a tuple of length 2"
744                        ))))
745                    }
746                } else {
747                    Some(Err(Error::StructureError(format!(
748                        "Value for key {key} is not an array"
749                    ))))
750                }
751            })
752            .transpose()
753    }
754}
755
756#[cfg(test)]
757mod tests {
758    use super::*;
759    use crate::{BinaryData, Bytes20, Bytes32, Identifier, Value};
760    use std::collections::BTreeMap;
761
762    // -----------------------------------------------------------------------
763    // Helper functions
764    // -----------------------------------------------------------------------
765
766    fn owned_map_with(entries: Vec<(&str, Value)>) -> BTreeMap<String, Value> {
767        entries
768            .into_iter()
769            .map(|(k, v)| (k.to_string(), v))
770            .collect()
771    }
772
773    fn ref_map_from(map: &BTreeMap<String, Value>) -> BTreeMap<String, &Value> {
774        map.iter().map(|(k, v)| (k.clone(), v)).collect()
775    }
776
777    // -----------------------------------------------------------------------
778    // Tests for BTreeMap<String, Value> (owned impl)
779    // -----------------------------------------------------------------------
780
781    mod owned_map {
782        use super::*;
783
784        // -- String tests --
785
786        #[test]
787        fn remove_string_success() {
788            let mut map = owned_map_with(vec![("name", Value::Text("alice".to_string()))]);
789            let result = map.remove_string("name").unwrap();
790            assert_eq!(result, "alice");
791            assert!(map.is_empty());
792        }
793
794        #[test]
795        fn remove_string_missing_key_errors() {
796            let mut map: BTreeMap<String, Value> = BTreeMap::new();
797            assert!(map.remove_string("name").is_err());
798        }
799
800        #[test]
801        fn remove_optional_string_returns_some() {
802            let mut map = owned_map_with(vec![("name", Value::Text("bob".to_string()))]);
803            let result = map.remove_optional_string("name").unwrap();
804            assert_eq!(result, Some("bob".to_string()));
805        }
806
807        #[test]
808        fn remove_optional_string_returns_none_for_missing() {
809            let mut map: BTreeMap<String, Value> = BTreeMap::new();
810            let result = map.remove_optional_string("name").unwrap();
811            assert_eq!(result, None);
812        }
813
814        #[test]
815        fn remove_optional_string_returns_none_for_null() {
816            let mut map = owned_map_with(vec![("name", Value::Null)]);
817            let result = map.remove_optional_string("name").unwrap();
818            assert_eq!(result, None);
819        }
820
821        // -- Float tests --
822
823        #[test]
824        fn remove_float_success() {
825            let mut map = owned_map_with(vec![("score", Value::Float(1.23))]);
826            let result = map.remove_float("score").unwrap();
827            assert!((result - 1.23).abs() < f64::EPSILON);
828        }
829
830        #[test]
831        fn remove_float_missing_key_errors() {
832            let mut map: BTreeMap<String, Value> = BTreeMap::new();
833            assert!(map.remove_float("score").is_err());
834        }
835
836        #[test]
837        fn remove_optional_float_returns_some() {
838            let mut map = owned_map_with(vec![("score", Value::Float(2.72))]);
839            let result = map.remove_optional_float("score").unwrap();
840            assert_eq!(result, Some(2.72));
841        }
842
843        #[test]
844        fn remove_optional_float_returns_none_for_missing() {
845            let mut map: BTreeMap<String, Value> = BTreeMap::new();
846            let result = map.remove_optional_float("score").unwrap();
847            assert_eq!(result, None);
848        }
849
850        #[test]
851        fn remove_optional_float_returns_none_for_null() {
852            let mut map = owned_map_with(vec![("score", Value::Null)]);
853            let result = map.remove_optional_float("score").unwrap();
854            assert_eq!(result, None);
855        }
856
857        // -- Integer tests --
858
859        #[test]
860        fn remove_integer_u64_success() {
861            let mut map = owned_map_with(vec![("age", Value::U64(42))]);
862            let result: u64 = map.remove_integer("age").unwrap();
863            assert_eq!(result, 42);
864        }
865
866        #[test]
867        fn remove_integer_i32_success() {
868            let mut map = owned_map_with(vec![("temp", Value::I32(-10))]);
869            let result: i32 = map.remove_integer("temp").unwrap();
870            assert_eq!(result, -10);
871        }
872
873        #[test]
874        fn remove_integer_missing_key_errors() {
875            let mut map: BTreeMap<String, Value> = BTreeMap::new();
876            let result: Result<u64, Error> = map.remove_integer("age");
877            assert!(result.is_err());
878        }
879
880        #[test]
881        fn remove_optional_integer_returns_some() {
882            let mut map = owned_map_with(vec![("count", Value::U32(7))]);
883            let result: Option<u32> = map.remove_optional_integer("count").unwrap();
884            assert_eq!(result, Some(7));
885        }
886
887        #[test]
888        fn remove_optional_integer_returns_none_for_missing() {
889            let mut map: BTreeMap<String, Value> = BTreeMap::new();
890            let result: Option<u32> = map.remove_optional_integer("count").unwrap();
891            assert_eq!(result, None);
892        }
893
894        #[test]
895        fn remove_optional_integer_returns_none_for_null() {
896            let mut map = owned_map_with(vec![("count", Value::Null)]);
897            let result: Option<u32> = map.remove_optional_integer("count").unwrap();
898            assert_eq!(result, None);
899        }
900
901        // -- Bool tests --
902
903        #[test]
904        fn remove_bool_success() {
905            let mut map = owned_map_with(vec![("active", Value::Bool(true))]);
906            let result = map.remove_bool("active").unwrap();
907            assert!(result);
908        }
909
910        #[test]
911        fn remove_bool_missing_key_errors() {
912            let mut map: BTreeMap<String, Value> = BTreeMap::new();
913            assert!(map.remove_bool("active").is_err());
914        }
915
916        #[test]
917        fn remove_optional_bool_returns_some() {
918            let mut map = owned_map_with(vec![("flag", Value::Bool(false))]);
919            let result = map.remove_optional_bool("flag").unwrap();
920            assert_eq!(result, Some(false));
921        }
922
923        #[test]
924        fn remove_optional_bool_returns_none_for_missing() {
925            let mut map: BTreeMap<String, Value> = BTreeMap::new();
926            let result = map.remove_optional_bool("flag").unwrap();
927            assert_eq!(result, None);
928        }
929
930        #[test]
931        fn remove_optional_bool_returns_none_for_null() {
932            let mut map = owned_map_with(vec![("flag", Value::Null)]);
933            let result = map.remove_optional_bool("flag").unwrap();
934            assert_eq!(result, None);
935        }
936
937        // -- Hash256 bytes tests --
938
939        #[test]
940        fn remove_hash256_bytes_success() {
941            let hash = [1u8; 32];
942            let mut map = owned_map_with(vec![("hash", Value::Bytes32(hash))]);
943            let result = map.remove_hash256_bytes("hash").unwrap();
944            assert_eq!(result, hash);
945        }
946
947        #[test]
948        fn remove_hash256_bytes_missing_key_errors() {
949            let mut map: BTreeMap<String, Value> = BTreeMap::new();
950            assert!(map.remove_hash256_bytes("hash").is_err());
951        }
952
953        #[test]
954        fn remove_optional_hash256_bytes_returns_some() {
955            let hash = [2u8; 32];
956            let mut map = owned_map_with(vec![("hash", Value::Bytes32(hash))]);
957            let result = map.remove_optional_hash256_bytes("hash").unwrap();
958            assert_eq!(result, Some(hash));
959        }
960
961        #[test]
962        fn remove_optional_hash256_bytes_returns_none_for_missing() {
963            let mut map: BTreeMap<String, Value> = BTreeMap::new();
964            let result = map.remove_optional_hash256_bytes("hash").unwrap();
965            assert_eq!(result, None);
966        }
967
968        #[test]
969        fn remove_optional_hash256_bytes_returns_none_for_null() {
970            let mut map = owned_map_with(vec![("hash", Value::Null)]);
971            let result = map.remove_optional_hash256_bytes("hash").unwrap();
972            assert_eq!(result, None);
973        }
974
975        // -- Bytes tests --
976
977        #[test]
978        fn remove_bytes_success() {
979            let bytes = vec![1, 2, 3, 4];
980            let mut map = owned_map_with(vec![("data", Value::Bytes(bytes.clone()))]);
981            let result = map.remove_bytes("data").unwrap();
982            assert_eq!(result, bytes);
983        }
984
985        #[test]
986        fn remove_bytes_missing_key_errors() {
987            let mut map: BTreeMap<String, Value> = BTreeMap::new();
988            assert!(map.remove_bytes("data").is_err());
989        }
990
991        #[test]
992        fn remove_optional_bytes_returns_some() {
993            let bytes = vec![5, 6, 7];
994            let mut map = owned_map_with(vec![("data", Value::Bytes(bytes.clone()))]);
995            let result = map.remove_optional_bytes("data").unwrap();
996            assert_eq!(result, Some(bytes));
997        }
998
999        #[test]
1000        fn remove_optional_bytes_returns_none_for_missing() {
1001            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1002            let result = map.remove_optional_bytes("data").unwrap();
1003            assert_eq!(result, None);
1004        }
1005
1006        #[test]
1007        fn remove_optional_bytes_returns_none_for_null() {
1008            let mut map = owned_map_with(vec![("data", Value::Null)]);
1009            let result = map.remove_optional_bytes("data").unwrap();
1010            assert_eq!(result, None);
1011        }
1012
1013        // -- Identifier tests --
1014
1015        #[test]
1016        fn remove_identifier_success() {
1017            let id_bytes = [3u8; 32];
1018            let mut map = owned_map_with(vec![("id", Value::Identifier(id_bytes))]);
1019            let result = map.remove_identifier("id").unwrap();
1020            assert_eq!(result, Identifier::from(id_bytes));
1021        }
1022
1023        #[test]
1024        fn remove_identifier_missing_key_errors() {
1025            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1026            assert!(map.remove_identifier("id").is_err());
1027        }
1028
1029        #[test]
1030        fn remove_optional_identifier_returns_some() {
1031            let id_bytes = [4u8; 32];
1032            let mut map = owned_map_with(vec![("id", Value::Identifier(id_bytes))]);
1033            let result = map.remove_optional_identifier("id").unwrap();
1034            assert_eq!(result, Some(Identifier::from(id_bytes)));
1035        }
1036
1037        #[test]
1038        fn remove_optional_identifier_returns_none_for_missing() {
1039            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1040            let result = map.remove_optional_identifier("id").unwrap();
1041            assert_eq!(result, None);
1042        }
1043
1044        #[test]
1045        fn remove_optional_identifier_returns_none_for_null() {
1046            let mut map = owned_map_with(vec![("id", Value::Null)]);
1047            let result = map.remove_optional_identifier("id").unwrap();
1048            assert_eq!(result, None);
1049        }
1050
1051        // -- BinaryData tests --
1052
1053        #[test]
1054        fn remove_binary_data_success() {
1055            let bytes = vec![10, 20, 30];
1056            let mut map = owned_map_with(vec![("bin", Value::Bytes(bytes.clone()))]);
1057            let result = map.remove_binary_data("bin").unwrap();
1058            assert_eq!(result, BinaryData(bytes));
1059        }
1060
1061        #[test]
1062        fn remove_binary_data_missing_key_errors() {
1063            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1064            assert!(map.remove_binary_data("bin").is_err());
1065        }
1066
1067        #[test]
1068        fn remove_optional_binary_data_returns_some() {
1069            let bytes = vec![40, 50];
1070            let mut map = owned_map_with(vec![("bin", Value::Bytes(bytes.clone()))]);
1071            let result = map.remove_optional_binary_data("bin").unwrap();
1072            assert_eq!(result, Some(BinaryData(bytes)));
1073        }
1074
1075        #[test]
1076        fn remove_optional_binary_data_returns_none_for_missing() {
1077            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1078            let result = map.remove_optional_binary_data("bin").unwrap();
1079            assert_eq!(result, None);
1080        }
1081
1082        #[test]
1083        fn remove_optional_binary_data_returns_none_for_null() {
1084            let mut map = owned_map_with(vec![("bin", Value::Null)]);
1085            let result = map.remove_optional_binary_data("bin").unwrap();
1086            assert_eq!(result, None);
1087        }
1088
1089        // -- Bytes32 tests --
1090
1091        #[test]
1092        fn remove_bytes_32_success() {
1093            let b32 = [5u8; 32];
1094            let mut map = owned_map_with(vec![("b32", Value::Bytes32(b32))]);
1095            let result = map.remove_bytes_32("b32").unwrap();
1096            assert_eq!(result, Bytes32(b32));
1097        }
1098
1099        #[test]
1100        fn remove_bytes_32_missing_key_errors() {
1101            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1102            assert!(map.remove_bytes_32("b32").is_err());
1103        }
1104
1105        #[test]
1106        fn remove_optional_bytes_32_returns_some() {
1107            let b32 = [6u8; 32];
1108            let mut map = owned_map_with(vec![("b32", Value::Bytes32(b32))]);
1109            let result = map.remove_optional_bytes_32("b32").unwrap();
1110            assert_eq!(result, Some(Bytes32(b32)));
1111        }
1112
1113        #[test]
1114        fn remove_optional_bytes_32_returns_none_for_missing() {
1115            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1116            let result = map.remove_optional_bytes_32("b32").unwrap();
1117            assert_eq!(result, None);
1118        }
1119
1120        #[test]
1121        fn remove_optional_bytes_32_returns_none_for_null() {
1122            let mut map = owned_map_with(vec![("b32", Value::Null)]);
1123            let result = map.remove_optional_bytes_32("b32").unwrap();
1124            assert_eq!(result, None);
1125        }
1126
1127        // -- Bytes20 tests --
1128
1129        #[test]
1130        fn remove_bytes_20_success() {
1131            let b20 = [7u8; 20];
1132            let mut map = owned_map_with(vec![("b20", Value::Bytes20(b20))]);
1133            let result = map.remove_bytes_20("b20").unwrap();
1134            assert_eq!(result, Bytes20(b20));
1135        }
1136
1137        #[test]
1138        fn remove_bytes_20_missing_key_errors() {
1139            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1140            assert!(map.remove_bytes_20("b20").is_err());
1141        }
1142
1143        #[test]
1144        fn remove_optional_bytes_20_returns_some() {
1145            let b20 = [8u8; 20];
1146            let mut map = owned_map_with(vec![("b20", Value::Bytes20(b20))]);
1147            let result = map.remove_optional_bytes_20("b20").unwrap();
1148            assert_eq!(result, Some(Bytes20(b20)));
1149        }
1150
1151        #[test]
1152        fn remove_optional_bytes_20_returns_none_for_missing() {
1153            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1154            let result = map.remove_optional_bytes_20("b20").unwrap();
1155            assert_eq!(result, None);
1156        }
1157
1158        #[test]
1159        fn remove_optional_bytes_20_returns_none_for_null() {
1160            let mut map = owned_map_with(vec![("b20", Value::Null)]);
1161            let result = map.remove_optional_bytes_20("b20").unwrap();
1162            assert_eq!(result, None);
1163        }
1164
1165        // -- Hash256s (array of hashes) tests --
1166
1167        #[test]
1168        fn remove_hash256s_success() {
1169            let h1 = [1u8; 32];
1170            let h2 = [2u8; 32];
1171            let mut map = owned_map_with(vec![(
1172                "hashes",
1173                Value::Array(vec![Value::Bytes32(h1), Value::Bytes32(h2)]),
1174            )]);
1175            let result = map.remove_hash256s("hashes").unwrap();
1176            assert_eq!(result, vec![h1, h2]);
1177        }
1178
1179        #[test]
1180        fn remove_hash256s_missing_key_errors() {
1181            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1182            assert!(map.remove_hash256s("hashes").is_err());
1183        }
1184
1185        #[test]
1186        fn remove_optional_hash256s_returns_some() {
1187            let h1 = [3u8; 32];
1188            let mut map = owned_map_with(vec![("hashes", Value::Array(vec![Value::Bytes32(h1)]))]);
1189            let result = map.remove_optional_hash256s("hashes").unwrap();
1190            assert_eq!(result, Some(vec![h1]));
1191        }
1192
1193        #[test]
1194        fn remove_optional_hash256s_returns_none_for_missing() {
1195            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1196            let result = map.remove_optional_hash256s("hashes").unwrap();
1197            assert_eq!(result, None);
1198        }
1199
1200        #[test]
1201        fn remove_optional_hash256s_returns_none_for_null() {
1202            let mut map = owned_map_with(vec![("hashes", Value::Null)]);
1203            let result = map.remove_optional_hash256s("hashes").unwrap();
1204            assert_eq!(result, None);
1205        }
1206
1207        #[test]
1208        fn remove_optional_hash256s_returns_none_for_non_array() {
1209            let mut map = owned_map_with(vec![("hashes", Value::Text("not_array".to_string()))]);
1210            let result = map.remove_optional_hash256s("hashes").unwrap();
1211            assert_eq!(result, None);
1212        }
1213
1214        // -- Identifiers (array) tests --
1215
1216        #[test]
1217        fn remove_identifiers_success() {
1218            let id1 = [10u8; 32];
1219            let id2 = [20u8; 32];
1220            let mut map = owned_map_with(vec![(
1221                "ids",
1222                Value::Array(vec![Value::Identifier(id1), Value::Identifier(id2)]),
1223            )]);
1224            let result = map.remove_identifiers("ids").unwrap();
1225            assert_eq!(result, vec![Identifier::from(id1), Identifier::from(id2)]);
1226        }
1227
1228        #[test]
1229        fn remove_identifiers_missing_key_errors() {
1230            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1231            assert!(map.remove_identifiers("ids").is_err());
1232        }
1233
1234        #[test]
1235        fn remove_optional_identifiers_returns_some() {
1236            let id = [30u8; 32];
1237            let mut map = owned_map_with(vec![("ids", Value::Array(vec![Value::Identifier(id)]))]);
1238            let result = map.remove_optional_identifiers("ids").unwrap();
1239            assert_eq!(result, Some(vec![Identifier::from(id)]));
1240        }
1241
1242        #[test]
1243        fn remove_optional_identifiers_returns_none_for_missing() {
1244            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1245            let result = map.remove_optional_identifiers("ids").unwrap();
1246            assert_eq!(result, None);
1247        }
1248
1249        #[test]
1250        fn remove_optional_identifiers_returns_none_for_null() {
1251            let mut map = owned_map_with(vec![("ids", Value::Null)]);
1252            let result = map.remove_optional_identifiers("ids").unwrap();
1253            assert_eq!(result, None);
1254        }
1255
1256        #[test]
1257        fn remove_optional_identifiers_returns_none_for_non_array() {
1258            let mut map = owned_map_with(vec![("ids", Value::U64(999))]);
1259            let result = map.remove_optional_identifiers("ids").unwrap();
1260            assert_eq!(result, None);
1261        }
1262
1263        // -- Map as BTreeMap tests --
1264
1265        #[test]
1266        fn remove_map_as_btree_map_success() {
1267            let inner_map = vec![
1268                (Value::Text("a".to_string()), Value::U64(1)),
1269                (Value::Text("b".to_string()), Value::U64(2)),
1270            ];
1271            let mut map = owned_map_with(vec![("m", Value::Map(inner_map))]);
1272            let result: BTreeMap<String, u64> = map.remove_map_as_btree_map("m").unwrap();
1273            assert_eq!(result.get("a"), Some(&1u64));
1274            assert_eq!(result.get("b"), Some(&2u64));
1275        }
1276
1277        #[test]
1278        fn remove_map_as_btree_map_missing_key_errors() {
1279            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1280            let result: Result<BTreeMap<String, String>, Error> = map.remove_map_as_btree_map("m");
1281            assert!(result.is_err());
1282        }
1283
1284        #[test]
1285        fn remove_optional_map_as_btree_map_returns_some() {
1286            let inner_map = vec![(Value::Text("x".to_string()), Value::Text("y".to_string()))];
1287            let mut map = owned_map_with(vec![("m", Value::Map(inner_map))]);
1288            let result: Option<BTreeMap<String, String>> =
1289                map.remove_optional_map_as_btree_map("m").unwrap();
1290            assert!(result.is_some());
1291            let inner = result.unwrap();
1292            assert_eq!(inner.get("x"), Some(&"y".to_string()));
1293        }
1294
1295        #[test]
1296        fn remove_optional_map_as_btree_map_returns_none_for_missing() {
1297            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1298            let result: Option<BTreeMap<String, String>> =
1299                map.remove_optional_map_as_btree_map("m").unwrap();
1300            assert_eq!(result, None);
1301        }
1302
1303        #[test]
1304        fn remove_optional_map_as_btree_map_returns_none_for_null() {
1305            let mut map = owned_map_with(vec![("m", Value::Null)]);
1306            let result: Option<BTreeMap<String, String>> =
1307                map.remove_optional_map_as_btree_map("m").unwrap();
1308            assert_eq!(result, None);
1309        }
1310
1311        // -- Map keep values as platform value tests --
1312
1313        #[test]
1314        fn remove_map_as_btree_map_keep_values_success() {
1315            let inner_map = vec![
1316                (Value::Text("k1".to_string()), Value::Bool(true)),
1317                (Value::Text("k2".to_string()), Value::Float(1.5)),
1318            ];
1319            let mut map = owned_map_with(vec![("m", Value::Map(inner_map))]);
1320            let result: BTreeMap<String, Value> = map
1321                .remove_map_as_btree_map_keep_values_as_platform_value::<String, Value>("m")
1322                .unwrap();
1323            assert_eq!(result.get("k1"), Some(&Value::Bool(true)));
1324            assert_eq!(result.get("k2"), Some(&Value::Float(1.5)));
1325        }
1326
1327        #[test]
1328        fn remove_map_as_btree_map_keep_values_missing_key_errors() {
1329            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1330            let result: Result<BTreeMap<String, Value>, Error> =
1331                map.remove_map_as_btree_map_keep_values_as_platform_value::<String, Value>("m");
1332            assert!(result.is_err());
1333        }
1334
1335        #[test]
1336        fn remove_optional_map_keep_values_returns_none_for_null() {
1337            let mut map = owned_map_with(vec![("m", Value::Null)]);
1338            let result: Option<BTreeMap<String, Value>> = map
1339                .remove_optional_map_as_btree_map_keep_values_as_platform_value("m")
1340                .unwrap();
1341            assert_eq!(result, None);
1342        }
1343
1344        #[test]
1345        fn remove_optional_map_keep_values_returns_none_for_missing() {
1346            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1347            let result: Option<BTreeMap<String, Value>> = map
1348                .remove_optional_map_as_btree_map_keep_values_as_platform_value("m")
1349                .unwrap();
1350            assert_eq!(result, None);
1351        }
1352
1353        // -- Removal actually removes the key from the map --
1354
1355        #[test]
1356        fn removal_removes_key_from_map() {
1357            let mut map = owned_map_with(vec![
1358                ("a", Value::Text("hello".to_string())),
1359                ("b", Value::U64(42)),
1360            ]);
1361            assert_eq!(map.len(), 2);
1362            let _ = map.remove_string("a");
1363            assert_eq!(map.len(), 1);
1364            assert!(!map.contains_key("a"));
1365            assert!(map.contains_key("b"));
1366        }
1367
1368        // -- Integer type edge cases --
1369
1370        #[test]
1371        fn remove_integer_u8() {
1372            let mut map = owned_map_with(vec![("x", Value::U8(255))]);
1373            let result: u8 = map.remove_integer("x").unwrap();
1374            assert_eq!(result, 255);
1375        }
1376
1377        #[test]
1378        fn remove_integer_i16() {
1379            let mut map = owned_map_with(vec![("x", Value::I16(-100))]);
1380            let result: i16 = map.remove_integer("x").unwrap();
1381            assert_eq!(result, -100);
1382        }
1383
1384        #[test]
1385        fn remove_integer_u128() {
1386            let mut map = owned_map_with(vec![("x", Value::U128(u128::MAX))]);
1387            let result: u128 = map.remove_integer("x").unwrap();
1388            assert_eq!(result, u128::MAX);
1389        }
1390
1391        #[test]
1392        fn remove_integer_i128() {
1393            let mut map = owned_map_with(vec![("x", Value::I128(i128::MIN))]);
1394            let result: i128 = map.remove_integer("x").unwrap();
1395            assert_eq!(result, i128::MIN);
1396        }
1397
1398        // -- Tuple tests --
1399
1400        #[test]
1401        fn remove_tuple_success() {
1402            let mut map = owned_map_with(vec![(
1403                "pair",
1404                Value::Array(vec![
1405                    Value::Text("key".to_string()),
1406                    Value::Text("value".to_string()),
1407                ]),
1408            )]);
1409            let result: (String, String) = map.remove_tuple("pair").unwrap();
1410            assert_eq!(result, ("key".to_string(), "value".to_string()));
1411        }
1412
1413        #[test]
1414        fn remove_tuple_missing_key_errors() {
1415            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1416            let result: Result<(String, String), Error> = map.remove_tuple("pair");
1417            assert!(result.is_err());
1418        }
1419
1420        #[test]
1421        fn remove_optional_tuple_returns_some() {
1422            let mut map = owned_map_with(vec![(
1423                "pair",
1424                Value::Array(vec![
1425                    Value::Text("a".to_string()),
1426                    Value::Text("b".to_string()),
1427                ]),
1428            )]);
1429            let result: Option<(String, String)> = map.remove_optional_tuple("pair").unwrap();
1430            assert_eq!(result, Some(("a".to_string(), "b".to_string())));
1431        }
1432
1433        #[test]
1434        fn remove_optional_tuple_returns_none_for_missing() {
1435            let mut map: BTreeMap<String, Value> = BTreeMap::new();
1436            let result: Option<(String, String)> = map.remove_optional_tuple("pair").unwrap();
1437            assert_eq!(result, None);
1438        }
1439
1440        #[test]
1441        fn remove_optional_tuple_returns_none_for_null() {
1442            let mut map = owned_map_with(vec![("pair", Value::Null)]);
1443            let result: Option<(String, String)> = map.remove_optional_tuple("pair").unwrap();
1444            assert_eq!(result, None);
1445        }
1446
1447        #[test]
1448        fn remove_optional_tuple_wrong_length_errors() {
1449            let mut map = owned_map_with(vec![(
1450                "pair",
1451                Value::Array(vec![Value::Text("only_one".to_string())]),
1452            )]);
1453            let result: Result<Option<(String, String)>, Error> = map.remove_optional_tuple("pair");
1454            assert!(result.is_err());
1455        }
1456
1457        #[test]
1458        fn remove_optional_tuple_non_array_errors() {
1459            let mut map = owned_map_with(vec![("pair", Value::Text("not_an_array".to_string()))]);
1460            let result: Result<Option<(String, String)>, Error> = map.remove_optional_tuple("pair");
1461            assert!(result.is_err());
1462        }
1463
1464        #[test]
1465        fn remove_optional_tuple_three_elements_errors() {
1466            let mut map = owned_map_with(vec![(
1467                "pair",
1468                Value::Array(vec![
1469                    Value::Text("a".to_string()),
1470                    Value::Text("b".to_string()),
1471                    Value::Text("c".to_string()),
1472                ]),
1473            )]);
1474            let result: Result<Option<(String, String)>, Error> = map.remove_optional_tuple("pair");
1475            assert!(result.is_err());
1476        }
1477
1478        #[test]
1479        fn remove_optional_tuple_empty_array_errors() {
1480            let mut map = owned_map_with(vec![("pair", Value::Array(vec![]))]);
1481            let result: Result<Option<(String, String)>, Error> = map.remove_optional_tuple("pair");
1482            assert!(result.is_err());
1483        }
1484    }
1485
1486    // -----------------------------------------------------------------------
1487    // Tests for BTreeMap<String, &Value> (ref impl)
1488    // -----------------------------------------------------------------------
1489
1490    mod ref_map {
1491        use super::*;
1492
1493        // -- String tests --
1494
1495        #[test]
1496        fn remove_string_success() {
1497            let source = owned_map_with(vec![("name", Value::Text("alice".to_string()))]);
1498            let mut map = ref_map_from(&source);
1499            let result = map.remove_string("name").unwrap();
1500            assert_eq!(result, "alice");
1501        }
1502
1503        #[test]
1504        fn remove_string_missing_key_errors() {
1505            let mut map: BTreeMap<String, &Value> = BTreeMap::new();
1506            assert!(map.remove_string("name").is_err());
1507        }
1508
1509        #[test]
1510        fn remove_optional_string_returns_some() {
1511            let source = owned_map_with(vec![("name", Value::Text("bob".to_string()))]);
1512            let mut map = ref_map_from(&source);
1513            let result = map.remove_optional_string("name").unwrap();
1514            assert_eq!(result, Some("bob".to_string()));
1515        }
1516
1517        #[test]
1518        fn remove_optional_string_returns_none_for_missing() {
1519            let mut map: BTreeMap<String, &Value> = BTreeMap::new();
1520            let result = map.remove_optional_string("name").unwrap();
1521            assert_eq!(result, None);
1522        }
1523
1524        #[test]
1525        fn remove_optional_string_returns_none_for_null() {
1526            let source = owned_map_with(vec![("name", Value::Null)]);
1527            let mut map = ref_map_from(&source);
1528            let result = map.remove_optional_string("name").unwrap();
1529            assert_eq!(result, None);
1530        }
1531
1532        // -- Float tests --
1533
1534        #[test]
1535        fn remove_float_success() {
1536            let source = owned_map_with(vec![("f", Value::Float(2.5))]);
1537            let mut map = ref_map_from(&source);
1538            let result = map.remove_float("f").unwrap();
1539            assert!((result - 2.5).abs() < f64::EPSILON);
1540        }
1541
1542        #[test]
1543        fn remove_float_missing_key_errors() {
1544            let mut map: BTreeMap<String, &Value> = BTreeMap::new();
1545            assert!(map.remove_float("f").is_err());
1546        }
1547
1548        #[test]
1549        fn remove_optional_float_returns_none_for_null() {
1550            let source = owned_map_with(vec![("f", Value::Null)]);
1551            let mut map = ref_map_from(&source);
1552            let result = map.remove_optional_float("f").unwrap();
1553            assert_eq!(result, None);
1554        }
1555
1556        // -- Integer tests --
1557
1558        #[test]
1559        fn remove_integer_success() {
1560            let source = owned_map_with(vec![("num", Value::U64(99))]);
1561            let mut map = ref_map_from(&source);
1562            let result: u64 = map.remove_integer("num").unwrap();
1563            assert_eq!(result, 99);
1564        }
1565
1566        #[test]
1567        fn remove_integer_missing_key_errors() {
1568            let mut map: BTreeMap<String, &Value> = BTreeMap::new();
1569            let result: Result<u64, Error> = map.remove_integer("num");
1570            assert!(result.is_err());
1571        }
1572
1573        #[test]
1574        fn remove_optional_integer_returns_none_for_null() {
1575            let source = owned_map_with(vec![("num", Value::Null)]);
1576            let mut map = ref_map_from(&source);
1577            let result: Option<u64> = map.remove_optional_integer("num").unwrap();
1578            assert_eq!(result, None);
1579        }
1580
1581        // -- Bool tests --
1582
1583        #[test]
1584        fn remove_bool_success() {
1585            let source = owned_map_with(vec![("flag", Value::Bool(true))]);
1586            let mut map = ref_map_from(&source);
1587            let result = map.remove_bool("flag").unwrap();
1588            assert!(result);
1589        }
1590
1591        #[test]
1592        fn remove_optional_bool_returns_none_for_null() {
1593            let source = owned_map_with(vec![("flag", Value::Null)]);
1594            let mut map = ref_map_from(&source);
1595            let result = map.remove_optional_bool("flag").unwrap();
1596            assert_eq!(result, None);
1597        }
1598
1599        // -- Hash256 tests --
1600
1601        #[test]
1602        fn remove_hash256_bytes_success() {
1603            let hash = [9u8; 32];
1604            let source = owned_map_with(vec![("h", Value::Bytes32(hash))]);
1605            let mut map = ref_map_from(&source);
1606            let result = map.remove_hash256_bytes("h").unwrap();
1607            assert_eq!(result, hash);
1608        }
1609
1610        #[test]
1611        fn remove_optional_hash256_bytes_returns_none_for_null() {
1612            let source = owned_map_with(vec![("h", Value::Null)]);
1613            let mut map = ref_map_from(&source);
1614            let result = map.remove_optional_hash256_bytes("h").unwrap();
1615            assert_eq!(result, None);
1616        }
1617
1618        // -- Bytes tests --
1619
1620        #[test]
1621        fn remove_bytes_success() {
1622            let bytes = vec![1, 2, 3];
1623            let source = owned_map_with(vec![("b", Value::Bytes(bytes.clone()))]);
1624            let mut map = ref_map_from(&source);
1625            let result = map.remove_bytes("b").unwrap();
1626            assert_eq!(result, bytes);
1627        }
1628
1629        #[test]
1630        fn remove_optional_bytes_returns_none_for_null() {
1631            let source = owned_map_with(vec![("b", Value::Null)]);
1632            let mut map = ref_map_from(&source);
1633            let result = map.remove_optional_bytes("b").unwrap();
1634            assert_eq!(result, None);
1635        }
1636
1637        // -- Identifier tests --
1638
1639        #[test]
1640        fn remove_identifier_success() {
1641            let id_bytes = [11u8; 32];
1642            let source = owned_map_with(vec![("id", Value::Identifier(id_bytes))]);
1643            let mut map = ref_map_from(&source);
1644            let result = map.remove_identifier("id").unwrap();
1645            assert_eq!(result, Identifier::from(id_bytes));
1646        }
1647
1648        #[test]
1649        fn remove_optional_identifier_returns_none_for_null() {
1650            let source = owned_map_with(vec![("id", Value::Null)]);
1651            let mut map = ref_map_from(&source);
1652            let result = map.remove_optional_identifier("id").unwrap();
1653            assert_eq!(result, None);
1654        }
1655
1656        // -- BinaryData tests --
1657
1658        #[test]
1659        fn remove_binary_data_success() {
1660            let bytes = vec![100, 200];
1661            let source = owned_map_with(vec![("bd", Value::Bytes(bytes.clone()))]);
1662            let mut map = ref_map_from(&source);
1663            let result = map.remove_binary_data("bd").unwrap();
1664            assert_eq!(result, BinaryData(bytes));
1665        }
1666
1667        #[test]
1668        fn remove_optional_binary_data_returns_none_for_null() {
1669            let source = owned_map_with(vec![("bd", Value::Null)]);
1670            let mut map = ref_map_from(&source);
1671            let result = map.remove_optional_binary_data("bd").unwrap();
1672            assert_eq!(result, None);
1673        }
1674
1675        // -- Bytes32 tests --
1676
1677        #[test]
1678        fn remove_bytes_32_success() {
1679            let b32 = [12u8; 32];
1680            let source = owned_map_with(vec![("b32", Value::Bytes32(b32))]);
1681            let mut map = ref_map_from(&source);
1682            let result = map.remove_bytes_32("b32").unwrap();
1683            assert_eq!(result, Bytes32(b32));
1684        }
1685
1686        #[test]
1687        fn remove_optional_bytes_32_returns_none_for_null() {
1688            let source = owned_map_with(vec![("b32", Value::Null)]);
1689            let mut map = ref_map_from(&source);
1690            let result = map.remove_optional_bytes_32("b32").unwrap();
1691            assert_eq!(result, None);
1692        }
1693
1694        // -- Bytes20 tests --
1695
1696        #[test]
1697        fn remove_bytes_20_success() {
1698            let b20 = [13u8; 20];
1699            let source = owned_map_with(vec![("b20", Value::Bytes20(b20))]);
1700            let mut map = ref_map_from(&source);
1701            let result = map.remove_bytes_20("b20").unwrap();
1702            assert_eq!(result, Bytes20(b20));
1703        }
1704
1705        #[test]
1706        fn remove_optional_bytes_20_returns_none_for_null() {
1707            let source = owned_map_with(vec![("b20", Value::Null)]);
1708            let mut map = ref_map_from(&source);
1709            let result = map.remove_optional_bytes_20("b20").unwrap();
1710            assert_eq!(result, None);
1711        }
1712
1713        // -- Hash256s (array of hashes) tests --
1714
1715        #[test]
1716        fn remove_hash256s_success() {
1717            let h1 = [14u8; 32];
1718            let h2 = [15u8; 32];
1719            let source = owned_map_with(vec![(
1720                "hashes",
1721                Value::Array(vec![Value::Bytes32(h1), Value::Bytes32(h2)]),
1722            )]);
1723            let mut map = ref_map_from(&source);
1724            let result = map.remove_hash256s("hashes").unwrap();
1725            assert_eq!(result, vec![h1, h2]);
1726        }
1727
1728        #[test]
1729        fn remove_optional_hash256s_returns_none_for_null() {
1730            let source = owned_map_with(vec![("hashes", Value::Null)]);
1731            let mut map = ref_map_from(&source);
1732            let result = map.remove_optional_hash256s("hashes").unwrap();
1733            assert_eq!(result, None);
1734        }
1735
1736        #[test]
1737        fn remove_optional_hash256s_returns_none_for_non_array() {
1738            let source = owned_map_with(vec![("hashes", Value::U64(42))]);
1739            let mut map = ref_map_from(&source);
1740            let result = map.remove_optional_hash256s("hashes").unwrap();
1741            assert_eq!(result, None);
1742        }
1743
1744        // -- Identifiers (array) tests --
1745
1746        #[test]
1747        fn remove_identifiers_success() {
1748            let id1 = [16u8; 32];
1749            let source = owned_map_with(vec![("ids", Value::Array(vec![Value::Identifier(id1)]))]);
1750            let mut map = ref_map_from(&source);
1751            let result = map.remove_identifiers("ids").unwrap();
1752            assert_eq!(result, vec![Identifier::from(id1)]);
1753        }
1754
1755        #[test]
1756        fn remove_optional_identifiers_returns_none_for_null() {
1757            let source = owned_map_with(vec![("ids", Value::Null)]);
1758            let mut map = ref_map_from(&source);
1759            let result = map.remove_optional_identifiers("ids").unwrap();
1760            assert_eq!(result, None);
1761        }
1762
1763        #[test]
1764        fn remove_optional_identifiers_returns_none_for_non_array() {
1765            let source = owned_map_with(vec![("ids", Value::Bool(false))]);
1766            let mut map = ref_map_from(&source);
1767            let result = map.remove_optional_identifiers("ids").unwrap();
1768            assert_eq!(result, None);
1769        }
1770
1771        // -- Map as BTreeMap tests --
1772
1773        #[test]
1774        fn remove_optional_map_as_btree_map_returns_none_for_null() {
1775            let source = owned_map_with(vec![("m", Value::Null)]);
1776            let mut map = ref_map_from(&source);
1777            let result: Option<BTreeMap<String, String>> =
1778                map.remove_optional_map_as_btree_map("m").unwrap();
1779            assert_eq!(result, None);
1780        }
1781
1782        #[test]
1783        fn remove_optional_map_as_btree_map_returns_none_for_missing() {
1784            let mut map: BTreeMap<String, &Value> = BTreeMap::new();
1785            let result: Option<BTreeMap<String, String>> =
1786                map.remove_optional_map_as_btree_map("m").unwrap();
1787            assert_eq!(result, None);
1788        }
1789
1790        // -- Map keep values tests --
1791
1792        #[test]
1793        fn remove_optional_map_keep_values_returns_none_for_null() {
1794            let source = owned_map_with(vec![("m", Value::Null)]);
1795            let mut map = ref_map_from(&source);
1796            let result: Option<BTreeMap<String, Value>> = map
1797                .remove_optional_map_as_btree_map_keep_values_as_platform_value("m")
1798                .unwrap();
1799            assert_eq!(result, None);
1800        }
1801
1802        // -- Ref map removal semantics --
1803
1804        #[test]
1805        fn ref_removal_removes_key_from_map() {
1806            let source = owned_map_with(vec![("a", Value::Bool(true)), ("b", Value::Bool(false))]);
1807            let mut map = ref_map_from(&source);
1808            assert_eq!(map.len(), 2);
1809            let _ = map.remove_bool("a");
1810            assert_eq!(map.len(), 1);
1811            assert!(!map.contains_key("a"));
1812        }
1813    }
1814}