ave_common/
wrapper.rs

1use std::{
2    io::{Read, Write},
3    ops::Deref,
4};
5
6use borsh::{BorshDeserialize, BorshSerialize};
7use serde::{Deserialize, Serialize};
8use serde_json::{Map, Number, Value};
9
10// Maximum recursion depth for deserializing nested structures
11// Prevents stack overflow from deeply nested JSON/Borsh data
12const MAX_RECURSION_DEPTH: usize = 128;
13
14// Maximum array/object length to prevent memory exhaustion
15const MAX_COLLECTION_SIZE: u32 = 100_000;
16
17/// Wrapper for `serde_json::Value` that implements `BorshSerialize` and `BorshDeserialize`.
18///
19/// This type bridges the gap between JSON-based state/event representations and the
20/// efficient Borsh binary serialization format used for WASM boundary crossings.
21/// It allows contract states and events (which are JSON-compatible) to be efficiently
22/// transferred between the WASM module and the host runtime.
23///
24/// The wrapper handles all JSON value types:
25/// - Bool: Boolean values
26/// - Number: Numeric values (f64, i64, u64)
27/// - String: Text values
28/// - Array: Ordered collections of values
29/// - Object: Key-value maps
30/// - Null: Null values
31#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
32pub struct ValueWrapper(pub Value);
33
34impl Deref for ValueWrapper {
35    type Target = Value;
36
37    fn deref(&self) -> &Self::Target {
38        &self.0
39    }
40}
41
42impl Default for ValueWrapper {
43    fn default() -> Self {
44        ValueWrapper(Value::Null)
45    }
46}
47
48/// Borsh serialization implementation for `ValueWrapper`.
49///
50/// Serializes JSON values into an efficient binary format using type tags.
51/// Each JSON type is prefixed with a discriminator byte to identify its type:
52/// - 0: Boolean
53/// - 1: Number (with sub-discriminator for f64=0, i64=1, u64=2)
54/// - 2: String
55/// - 3: Array
56/// - 4: Object
57/// - 5: Null
58impl BorshSerialize for ValueWrapper {
59    #[inline]
60    fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
61        match &self.0 {
62            // Serialize boolean: type tag (0) + boolean value
63            Value::Bool(data) => {
64                BorshSerialize::serialize(&0u8, writer)?;
65                BorshSerialize::serialize(&data, writer)
66            }
67            // Serialize number: type tag (1) + numeric sub-type tag + value
68            Value::Number(data) => {
69                BorshSerialize::serialize(&1u8, writer)?;
70                'data: {
71                    // Try f64 first
72                    if data.is_f64() {
73                        let Some(data) = data.as_f64() else {
74                            break 'data;
75                        };
76                        BorshSerialize::serialize(&0u8, writer)?;
77                        return BorshSerialize::serialize(&data, writer);
78                    }
79                    // Try i64
80                    else if data.is_i64() {
81                        let Some(data) = data.as_i64() else {
82                            break 'data;
83                        };
84                        BorshSerialize::serialize(&1u8, writer)?;
85                        return BorshSerialize::serialize(&data, writer);
86                    }
87                    // Try u64
88                    else if data.is_u64() {
89                        let Some(data) = data.as_u64() else {
90                            break 'data;
91                        };
92                        BorshSerialize::serialize(&2u8, writer)?;
93                        return BorshSerialize::serialize(&data, writer);
94                    }
95                }
96                Err(std::io::Error::new(
97                    std::io::ErrorKind::InvalidData,
98                    "Invalid number type",
99                ))
100            }
101            // Serialize string: type tag (2) + string data
102            Value::String(data) => {
103                BorshSerialize::serialize(&2u8, writer)?;
104                BorshSerialize::serialize(&data, writer)
105            }
106            // Serialize array: type tag (3) + length + elements
107            Value::Array(data) => {
108                BorshSerialize::serialize(&3u8, writer)?;
109                // Check array length fits in u32
110                let len = u32::try_from(data.len()).map_err(|_| {
111                    std::io::Error::new(
112                        std::io::ErrorKind::InvalidInput,
113                        format!(
114                            "Array too large to serialize: {} elements exceeds u32::MAX",
115                            data.len()
116                        ),
117                    )
118                })?;
119                BorshSerialize::serialize(&len, writer)?;
120                for element in data {
121                    let element = ValueWrapper(element.to_owned());
122                    BorshSerialize::serialize(&element, writer)?;
123                }
124                Ok(())
125            }
126            // Serialize object: type tag (4) + length + key-value pairs
127            Value::Object(data) => {
128                BorshSerialize::serialize(&4u8, writer)?;
129                // Check object length fits in u32
130                let len = u32::try_from(data.len()).map_err(|_| {
131                    std::io::Error::new(
132                        std::io::ErrorKind::InvalidInput,
133                        format!(
134                            "Object too large to serialize: {} keys exceeds u32::MAX",
135                            data.len()
136                        ),
137                    )
138                })?;
139                BorshSerialize::serialize(&len, writer)?;
140                for (key, value) in data {
141                    BorshSerialize::serialize(&key, writer)?;
142                    let value = ValueWrapper(value.to_owned());
143                    BorshSerialize::serialize(&value, writer)?;
144                }
145                Ok(())
146            }
147            // Serialize null: just type tag (5)
148            Value::Null => BorshSerialize::serialize(&5u8, writer),
149        }
150    }
151}
152
153/// Borsh deserialization implementation for `ValueWrapper`.
154///
155/// Deserializes binary Borsh data back into JSON values by reading type discriminators
156/// and reconstructing the appropriate JSON value type. This is the inverse of the
157/// serialization process.
158///
159/// The type tags used are:
160/// - 0: Boolean
161/// - 1: Number (with sub-discriminator for f64=0, i64=1, u64=2)
162/// - 2: String
163/// - 3: Array
164/// - 4: Object
165/// - 5: Null
166impl ValueWrapper {
167    /// Internal deserialization with recursion depth tracking.
168    ///
169    /// This prevents stack overflow attacks from deeply nested structures.
170    fn deserialize_reader_with_depth<R: Read>(
171        reader: &mut R,
172        depth: usize,
173    ) -> std::io::Result<Self> {
174        if depth > MAX_RECURSION_DEPTH {
175            return Err(std::io::Error::new(
176                std::io::ErrorKind::InvalidInput,
177                format!(
178                    "Recursion depth limit exceeded: maximum depth is {}",
179                    MAX_RECURSION_DEPTH
180                ),
181            ));
182        }
183
184        // Read the type discriminator byte
185        let order: u8 = BorshDeserialize::deserialize_reader(reader)?;
186        match order {
187            // Type 0: Boolean
188            0 => {
189                let data: bool = BorshDeserialize::deserialize_reader(reader)?;
190                Ok(ValueWrapper(Value::Bool(data)))
191            }
192            // Type 1: Number (requires reading numeric sub-type)
193            1 => {
194                let internal_order: u8 =
195                    BorshDeserialize::deserialize_reader(reader)?;
196                match internal_order {
197                    // Sub-type 0: f64
198                    0 => {
199                        let data: f64 =
200                            BorshDeserialize::deserialize_reader(reader)?;
201                        let Some(data_f64) = Number::from_f64(data) else {
202                            return Err(std::io::Error::new(
203                                std::io::ErrorKind::InvalidInput,
204                                format!("Invalid f64 Number: {}", data),
205                            ));
206                        };
207                        Ok(ValueWrapper(Value::Number(data_f64)))
208                    }
209                    // Sub-type 1: i64
210                    1 => {
211                        let data: i64 =
212                            BorshDeserialize::deserialize_reader(reader)?;
213                        Ok(ValueWrapper(Value::Number(Number::from(data))))
214                    }
215                    // Sub-type 2: u64
216                    2 => {
217                        let data: u64 =
218                            BorshDeserialize::deserialize_reader(reader)?;
219                        Ok(ValueWrapper(Value::Number(Number::from(data))))
220                    }
221                    _ => Err(std::io::Error::new(
222                        std::io::ErrorKind::InvalidInput,
223                        format!(
224                            "Invalid Number representation: {}",
225                            internal_order
226                        ),
227                    )),
228                }
229            }
230            // Type 2: String
231            2 => {
232                let data: String =
233                    BorshDeserialize::deserialize_reader(reader)?;
234                Ok(ValueWrapper(Value::String(data)))
235            }
236            // Type 3: Array (read length, then elements)
237            3 => {
238                let len = u32::deserialize_reader(reader)?;
239
240                // Security check: prevent excessive array sizes
241                if len > MAX_COLLECTION_SIZE {
242                    return Err(std::io::Error::new(
243                        std::io::ErrorKind::InvalidInput,
244                        format!(
245                            "Array size too large: {} exceeds maximum of {}",
246                            len, MAX_COLLECTION_SIZE
247                        ),
248                    ));
249                }
250
251                if len == 0 {
252                    Ok(ValueWrapper(Value::Array(Vec::new())))
253                } else {
254                    let mut result = Vec::with_capacity(len as usize);
255                    // Use checked arithmetic to prevent depth overflow
256                    let next_depth = depth.checked_add(1).ok_or_else(|| {
257                        std::io::Error::new(
258                            std::io::ErrorKind::InvalidInput,
259                            "Recursion depth counter overflow",
260                        )
261                    })?;
262                    for _ in 0..len {
263                        result.push(
264                            ValueWrapper::deserialize_reader_with_depth(
265                                reader, next_depth,
266                            )?
267                            .0,
268                        );
269                    }
270                    Ok(ValueWrapper(Value::Array(result)))
271                }
272            }
273            // Type 4: Object (read length, then key-value pairs)
274            4 => {
275                let len = u32::deserialize_reader(reader)?;
276
277                // Security check: prevent excessive object sizes
278                if len > MAX_COLLECTION_SIZE {
279                    return Err(std::io::Error::new(
280                        std::io::ErrorKind::InvalidInput,
281                        format!(
282                            "Object size too large: {} exceeds maximum of {}",
283                            len, MAX_COLLECTION_SIZE
284                        ),
285                    ));
286                }
287
288                let mut result = Map::new();
289                // Use checked arithmetic to prevent depth overflow
290                let next_depth = depth.checked_add(1).ok_or_else(|| {
291                    std::io::Error::new(
292                        std::io::ErrorKind::InvalidInput,
293                        "Recursion depth counter overflow",
294                    )
295                })?;
296                for _ in 0..len {
297                    let key = String::deserialize_reader(reader)?;
298                    let value = ValueWrapper::deserialize_reader_with_depth(
299                        reader, next_depth,
300                    )?;
301                    result.insert(key, value.0);
302                }
303                Ok(ValueWrapper(Value::Object(result)))
304            }
305            // Type 5: Null
306            5 => Ok(ValueWrapper(Value::Null)),
307            // Unknown type discriminator
308            _ => Err(std::io::Error::new(
309                std::io::ErrorKind::InvalidInput,
310                format!("Invalid Value representation: {}", order),
311            )),
312        }
313    }
314}
315
316impl BorshDeserialize for ValueWrapper {
317    #[inline]
318    fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self> {
319        // Start deserialization with depth 0
320        ValueWrapper::deserialize_reader_with_depth(reader, 0)
321    }
322}
323
324#[cfg(test)]
325mod tests {
326    use super::*;
327    use std::io::Cursor;
328
329    // Basic serialization round-trip: string values
330    #[test]
331    fn test_value_wrapper_string() {
332        let value = ValueWrapper(Value::String("test".to_owned()));
333        let vec = borsh::to_vec(&value).unwrap();
334        let value2: ValueWrapper =
335            BorshDeserialize::try_from_slice(&vec).unwrap();
336        assert_eq!(value, value2);
337    }
338
339    // Basic serialization round-trip: boolean values (true/false)
340    #[test]
341    fn test_value_wrapper_bool() {
342        let value = ValueWrapper(Value::Bool(true));
343        let vec = borsh::to_vec(&value).unwrap();
344        let value2: ValueWrapper =
345            BorshDeserialize::try_from_slice(&vec).unwrap();
346        assert_eq!(value, value2);
347
348        let value_false = ValueWrapper(Value::Bool(false));
349        let vec_false = borsh::to_vec(&value_false).unwrap();
350        let value2_false: ValueWrapper =
351            BorshDeserialize::try_from_slice(&vec_false).unwrap();
352        assert_eq!(value_false, value2_false);
353    }
354
355    // Basic serialization round-trip: f64 numbers
356    #[test]
357    fn test_value_wrapper_number_f64() {
358        let value =
359            ValueWrapper(Value::Number(Number::from_f64(3.14).unwrap()));
360        let vec = borsh::to_vec(&value).unwrap();
361        let value2: ValueWrapper =
362            BorshDeserialize::try_from_slice(&vec).unwrap();
363        assert_eq!(value, value2);
364    }
365
366    // Basic serialization round-trip: i64 numbers (negative values)
367    #[test]
368    fn test_value_wrapper_number_i64() {
369        let value = ValueWrapper(Value::Number(Number::from(-42i64)));
370        let vec = borsh::to_vec(&value).unwrap();
371        let value2: ValueWrapper =
372            BorshDeserialize::try_from_slice(&vec).unwrap();
373        assert_eq!(value, value2);
374    }
375
376    // Basic serialization round-trip: u64 numbers (positive values)
377    #[test]
378    fn test_value_wrapper_number_u64() {
379        let value = ValueWrapper(Value::Number(Number::from(12345u64)));
380        let vec = borsh::to_vec(&value).unwrap();
381        let value2: ValueWrapper =
382            BorshDeserialize::try_from_slice(&vec).unwrap();
383        assert_eq!(value, value2);
384    }
385
386    // Basic serialization round-trip: null values
387    #[test]
388    fn test_value_wrapper_null() {
389        let value = ValueWrapper(Value::Null);
390        let vec = borsh::to_vec(&value).unwrap();
391        let value2: ValueWrapper =
392            BorshDeserialize::try_from_slice(&vec).unwrap();
393        assert_eq!(value, value2);
394    }
395
396    // Arrays with mixed types serialize correctly
397    #[test]
398    fn test_value_wrapper_array() {
399        let value = ValueWrapper(Value::Array(vec![
400            Value::Bool(true),
401            Value::String("test".to_owned()),
402            Value::Number(Number::from(42)),
403            Value::Null,
404        ]));
405        let vec = borsh::to_vec(&value).unwrap();
406        let value2: ValueWrapper =
407            BorshDeserialize::try_from_slice(&vec).unwrap();
408        assert_eq!(value, value2);
409    }
410
411    // Empty arrays are handled correctly
412    #[test]
413    fn test_value_wrapper_empty_array() {
414        let value = ValueWrapper(Value::Array(vec![]));
415        let vec = borsh::to_vec(&value).unwrap();
416        let value2: ValueWrapper =
417            BorshDeserialize::try_from_slice(&vec).unwrap();
418        assert_eq!(value, value2);
419    }
420
421    // Objects with string keys and mixed value types
422    #[test]
423    fn test_value_wrapper_object() {
424        let mut map = Map::new();
425        map.insert("name".to_string(), Value::String("Alice".to_owned()));
426        map.insert("age".to_string(), Value::Number(Number::from(30)));
427        map.insert("active".to_string(), Value::Bool(true));
428
429        let value = ValueWrapper(Value::Object(map));
430        let vec = borsh::to_vec(&value).unwrap();
431        let value2: ValueWrapper =
432            BorshDeserialize::try_from_slice(&vec).unwrap();
433        assert_eq!(value, value2);
434    }
435
436    // Empty objects are handled correctly
437    #[test]
438    fn test_value_wrapper_empty_object() {
439        let value = ValueWrapper(Value::Object(Map::new()));
440        let vec = borsh::to_vec(&value).unwrap();
441        let value2: ValueWrapper =
442            BorshDeserialize::try_from_slice(&vec).unwrap();
443        assert_eq!(value, value2);
444    }
445
446    // Nested structures (objects within objects, arrays within objects)
447    #[test]
448    fn test_value_wrapper_nested_structure() {
449        let mut inner_map = Map::new();
450        inner_map.insert("x".to_string(), Value::Number(Number::from(1)));
451        inner_map.insert("y".to_string(), Value::Number(Number::from(2)));
452
453        let mut outer_map = Map::new();
454        outer_map.insert("point".to_string(), Value::Object(inner_map));
455        outer_map.insert(
456            "values".to_string(),
457            Value::Array(vec![
458                Value::Number(Number::from(1)),
459                Value::Number(Number::from(2)),
460                Value::Number(Number::from(3)),
461            ]),
462        );
463
464        let value = ValueWrapper(Value::Object(outer_map));
465        let vec = borsh::to_vec(&value).unwrap();
466        let value2: ValueWrapper =
467            BorshDeserialize::try_from_slice(&vec).unwrap();
468        assert_eq!(value, value2);
469    }
470
471    // Accepts structures at max recursion depth (128 levels)
472    #[test]
473    fn test_value_wrapper_max_recursion_depth() {
474        let mut value = Value::Null;
475        for _ in 0..MAX_RECURSION_DEPTH {
476            value = Value::Array(vec![value]);
477        }
478
479        let wrapper = ValueWrapper(value);
480        let vec = borsh::to_vec(&wrapper).unwrap();
481
482        let result: Result<ValueWrapper, _> =
483            BorshDeserialize::try_from_slice(&vec);
484        assert!(result.is_ok());
485    }
486
487    // Rejects structures exceeding max recursion depth (prevents stack overflow)
488    #[test]
489    fn test_value_wrapper_exceeds_recursion_depth() {
490        let mut value = Value::Null;
491        for _ in 0..=MAX_RECURSION_DEPTH {
492            value = Value::Array(vec![value]);
493        }
494
495        let wrapper = ValueWrapper(value);
496        let vec = borsh::to_vec(&wrapper).unwrap();
497
498        let result: Result<ValueWrapper, _> =
499            BorshDeserialize::try_from_slice(&vec);
500        assert!(result.is_err());
501        assert!(
502            result
503                .unwrap_err()
504                .to_string()
505                .contains("Recursion depth limit exceeded")
506        );
507    }
508
509    // Accepts arrays at max collection size (100,000 elements)
510    #[test]
511    fn test_value_wrapper_large_array() {
512        let large_array = vec![Value::Null; MAX_COLLECTION_SIZE as usize];
513        let value = ValueWrapper(Value::Array(large_array));
514        let vec = borsh::to_vec(&value).unwrap();
515        let value2: ValueWrapper =
516            BorshDeserialize::try_from_slice(&vec).unwrap();
517        assert_eq!(value, value2);
518    }
519
520    // Rejects arrays exceeding max size (prevents memory exhaustion)
521    #[test]
522    fn test_value_wrapper_array_size_overflow() {
523        let mut bytes = vec![3u8]; // Type tag for Array
524        let oversized_len = MAX_COLLECTION_SIZE + 1;
525        bytes.extend_from_slice(&oversized_len.to_le_bytes());
526
527        let result: Result<ValueWrapper, _> =
528            BorshDeserialize::try_from_slice(&bytes);
529        assert!(result.is_err());
530        assert!(
531            result
532                .unwrap_err()
533                .to_string()
534                .contains("Array size too large")
535        );
536    }
537
538    // Rejects objects exceeding max size (prevents memory exhaustion)
539    #[test]
540    fn test_value_wrapper_object_size_overflow() {
541        let mut bytes = vec![4u8]; // Type tag for Object
542        let oversized_len = MAX_COLLECTION_SIZE + 1;
543        bytes.extend_from_slice(&oversized_len.to_le_bytes());
544
545        let result: Result<ValueWrapper, _> =
546            BorshDeserialize::try_from_slice(&bytes);
547        assert!(result.is_err());
548        assert!(
549            result
550                .unwrap_err()
551                .to_string()
552                .contains("Object size too large")
553        );
554    }
555
556    // Rejects unknown type discriminators (valid: 0-5)
557    #[test]
558    fn test_value_wrapper_invalid_type_tag() {
559        let bytes = vec![6u8];
560
561        let result: Result<ValueWrapper, _> =
562            BorshDeserialize::try_from_slice(&bytes);
563        assert!(result.is_err());
564        assert!(
565            result
566                .unwrap_err()
567                .to_string()
568                .contains("Invalid Value representation")
569        );
570    }
571
572    // Rejects invalid number sub-types (valid: 0=f64, 1=i64, 2=u64)
573    #[test]
574    fn test_value_wrapper_invalid_number_type() {
575        let bytes = vec![1u8, 3u8];
576
577        let result: Result<ValueWrapper, _> =
578            BorshDeserialize::try_from_slice(&bytes);
579        assert!(result.is_err());
580        assert!(
581            result
582                .unwrap_err()
583                .to_string()
584                .contains("Invalid Number representation")
585        );
586    }
587
588    // Unicode strings (multi-byte characters, emojis) are handled correctly
589    #[test]
590    fn test_value_wrapper_unicode_strings() {
591        let value = ValueWrapper(Value::String("Hello δΈ–η•Œ 🌍".to_owned()));
592        let vec = borsh::to_vec(&value).unwrap();
593        let value2: ValueWrapper =
594            BorshDeserialize::try_from_slice(&vec).unwrap();
595        assert_eq!(value, value2);
596    }
597
598    // Empty strings are valid
599    #[test]
600    fn test_value_wrapper_empty_string() {
601        let value = ValueWrapper(Value::String(String::new()));
602        let vec = borsh::to_vec(&value).unwrap();
603        let value2: ValueWrapper =
604            BorshDeserialize::try_from_slice(&vec).unwrap();
605        assert_eq!(value, value2);
606    }
607
608    // Special float values: +0.0 and -0.0 are valid (but NaN/Infinity are not)
609    #[test]
610    fn test_value_wrapper_special_floats() {
611        let value = ValueWrapper(Value::Number(Number::from_f64(0.0).unwrap()));
612        let vec = borsh::to_vec(&value).unwrap();
613        let value2: ValueWrapper =
614            BorshDeserialize::try_from_slice(&vec).unwrap();
615        assert_eq!(value, value2);
616
617        let value =
618            ValueWrapper(Value::Number(Number::from_f64(-0.0).unwrap()));
619        let vec = borsh::to_vec(&value).unwrap();
620        let value2: ValueWrapper =
621            BorshDeserialize::try_from_slice(&vec).unwrap();
622        assert_eq!(value, value2);
623    }
624
625    // Clone trait works correctly
626    #[test]
627    fn test_value_wrapper_clone() {
628        let value = ValueWrapper(Value::String("test".to_owned()));
629        let cloned = value.clone();
630        assert_eq!(value, cloned);
631    }
632
633    // Debug trait produces readable output
634    #[test]
635    fn test_value_wrapper_debug() {
636        let value = ValueWrapper(Value::String("test".to_owned()));
637        let debug_str = format!("{:?}", value);
638        assert!(debug_str.contains("test"));
639    }
640
641    // Deref trait allows direct access to Value methods
642    #[test]
643    fn test_value_wrapper_as_str() {
644        let value = ValueWrapper(Value::String("hello".to_owned()));
645        assert_eq!(value.as_str(), Some("hello"));
646
647        let non_string = ValueWrapper(Value::Number(Number::from(42)));
648        assert_eq!(non_string.as_str(), None);
649    }
650
651    // Object key access via Deref (get method)
652    #[test]
653    fn test_value_wrapper_get() {
654        let mut map = Map::new();
655        map.insert("name".to_string(), Value::String("Alice".to_owned()));
656        map.insert("age".to_string(), Value::Number(Number::from(30)));
657
658        let value = ValueWrapper(Value::Object(map));
659        assert_eq!(value.get("name"), Some(&Value::String("Alice".to_owned())));
660        assert_eq!(value.get("age"), Some(&Value::Number(Number::from(30))));
661        assert_eq!(value.get("missing"), None);
662
663        let non_object =
664            ValueWrapper(Value::String("not an object".to_owned()));
665        assert_eq!(non_object.get("key"), None);
666    }
667
668    // Deref allows calling Value type-checking methods
669    #[test]
670    fn test_value_wrapper_deref() {
671        let value = ValueWrapper(Value::String("test".to_owned()));
672        assert!(value.is_string());
673        assert!(!value.is_number());
674
675        let number = ValueWrapper(Value::Number(Number::from(42)));
676        assert!(number.is_number());
677        assert!(!number.is_string());
678    }
679
680    // Default produces Null value
681    #[test]
682    fn test_value_wrapper_default() {
683        let value = ValueWrapper::default();
684        assert_eq!(value.0, Value::Null);
685        assert!(value.is_null());
686    }
687
688    // Hash trait allows use in HashMap/HashSet
689    #[test]
690    fn test_value_wrapper_hash() {
691        use std::collections::HashMap;
692
693        let wrapper1 = ValueWrapper(Value::String("key1".to_owned()));
694        let wrapper2 = ValueWrapper(Value::String("key2".to_owned()));
695
696        let mut map = HashMap::new();
697        map.insert(wrapper1.clone(), "value1");
698        map.insert(wrapper2.clone(), "value2");
699
700        assert_eq!(map.get(&wrapper1), Some(&"value1"));
701        assert_eq!(map.get(&wrapper2), Some(&"value2"));
702    }
703
704    // Helper: deserialize from raw bytes
705    fn deser(bytes: Vec<u8>) -> std::io::Result<ValueWrapper> {
706        let mut c = Cursor::new(bytes);
707        ValueWrapper::deserialize_reader(&mut c)
708    }
709
710    // Helper: push single byte (type discriminators)
711    fn push_u8(buf: &mut Vec<u8>, v: u8) {
712        buf.push(v);
713    }
714
715    // Helper: push u32 in little-endian (collection lengths)
716    fn push_u32(buf: &mut Vec<u8>, v: u32) {
717        buf.extend_from_slice(&v.to_le_bytes());
718    }
719
720    // Helper: push i64 in little-endian (signed integers)
721    fn push_i64(buf: &mut Vec<u8>, v: i64) {
722        buf.extend_from_slice(&v.to_le_bytes());
723    }
724
725    // Helper: push u64 in little-endian (unsigned integers)
726    fn push_u64(buf: &mut Vec<u8>, v: u64) {
727        buf.extend_from_slice(&v.to_le_bytes());
728    }
729
730    // Helper: push f64 in little-endian (floating point numbers)
731    fn push_f64(buf: &mut Vec<u8>, v: f64) {
732        buf.extend_from_slice(&v.to_le_bytes());
733    }
734
735    // Helper: push Borsh-encoded string (u32 length + UTF-8 bytes)
736    fn push_borsh_string(buf: &mut Vec<u8>, s: &str) {
737        let b = s.as_bytes();
738        push_u32(buf, b.len() as u32);
739        buf.extend_from_slice(b);
740    }
741
742    // Rejects invalid type discriminator (255 is not in 0-5 range)
743    #[test]
744    fn rejects_unknown_discriminator() {
745        let bytes = vec![255u8];
746        assert!(deser(bytes).is_err());
747    }
748
749    // Rejects invalid number sub-type (99 is not in 0-2 range)
750    #[test]
751    fn rejects_number_unknown_internal_order() {
752        let mut bytes = Vec::new();
753        push_u8(&mut bytes, 1); // Type: Number
754        push_u8(&mut bytes, 99); // invalid sub-type
755        assert!(deser(bytes).is_err());
756    }
757
758    // Rejects NaN values (not representable in JSON)
759    #[test]
760    fn rejects_nan_f64_number() {
761        let mut bytes = Vec::new();
762        push_u8(&mut bytes, 1); // Type: Number
763        push_u8(&mut bytes, 0); // Sub-type: f64
764        push_f64(&mut bytes, f64::NAN);
765        assert!(deser(bytes).is_err());
766    }
767
768    // Rejects Infinity values (not representable in JSON)
769    #[test]
770    fn rejects_infinite_f64_number() {
771        let mut bytes = Vec::new();
772        push_u8(&mut bytes, 1); // Type: Number
773        push_u8(&mut bytes, 0); // Sub-type: f64
774        push_f64(&mut bytes, f64::INFINITY);
775        assert!(deser(bytes).is_err());
776    }
777
778    // Rejects array length header exceeding MAX_COLLECTION_SIZE
779    #[test]
780    fn rejects_array_too_large() {
781        let mut bytes = Vec::new();
782        push_u8(&mut bytes, 3); // Type: Array
783        let len = (MAX_COLLECTION_SIZE as u32) + 1;
784        push_u32(&mut bytes, len);
785        assert!(deser(bytes).is_err());
786    }
787
788    // Rejects object length header exceeding MAX_COLLECTION_SIZE
789    #[test]
790    fn rejects_object_too_large() {
791        let mut bytes = Vec::new();
792        push_u8(&mut bytes, 4); // Type: Object
793        let len = (MAX_COLLECTION_SIZE as u32) + 1;
794        push_u32(&mut bytes, len);
795        assert!(deser(bytes).is_err());
796    }
797
798    // Rejects deeply nested arrays exceeding recursion limit
799    #[test]
800    fn rejects_recursion_depth_exceeded_nested_arrays() {
801        let mut bytes = Vec::new();
802
803        let levels = (MAX_RECURSION_DEPTH as usize) + 2;
804        for _ in 0..levels {
805            push_u8(&mut bytes, 3); // Array
806            push_u32(&mut bytes, 1); // len=1
807        }
808        push_u8(&mut bytes, 5); // Null
809
810        assert!(deser(bytes).is_err());
811    }
812
813    // Rejects invalid UTF-8 byte sequences in strings
814    #[test]
815    fn rejects_invalid_utf8_string() {
816        let mut bytes = Vec::new();
817        push_u8(&mut bytes, 2); // Type: String
818        push_u32(&mut bytes, 1); // length=1
819        bytes.push(0xFF); // invalid UTF-8 byte
820
821        assert!(deser(bytes).is_err());
822    }
823
824    // Rejects incomplete f64 value (missing 8 bytes)
825    #[test]
826    fn rejects_truncated_payload_mid_value() {
827        let mut bytes = Vec::new();
828        push_u8(&mut bytes, 1); // Number
829        push_u8(&mut bytes, 0); // f64
830        // missing 8 bytes for f64 value
831        assert!(deser(bytes).is_err());
832    }
833
834    // Rejects object with incomplete key-value pair (truncated value)
835    #[test]
836    fn rejects_object_with_truncated_kv_pair() {
837        let mut bytes = Vec::new();
838        push_u8(&mut bytes, 4); // Object
839        push_u32(&mut bytes, 1); // 1 pair
840
841        push_borsh_string(&mut bytes, "k");
842
843        push_u8(&mut bytes, 2); // String
844        push_u32(&mut bytes, 10); // claims length=10
845        // missing actual string bytes
846
847        assert!(deser(bytes).is_err());
848    }
849
850    // Rejects incomplete i64 value (only 3 bytes instead of 8)
851    #[test]
852    fn rejects_number_i64_ok_but_truncated() {
853        let mut bytes = Vec::new();
854        push_u8(&mut bytes, 1); // Number
855        push_u8(&mut bytes, 1); // i64
856
857        bytes.extend_from_slice(&[1, 2, 3]); // only 3 bytes
858        assert!(deser(bytes).is_err());
859    }
860
861    // Tests push_i64: serializes negative i64 correctly
862    #[test]
863    fn accepts_i64_number_via_push_i64() {
864        let mut bytes = Vec::new();
865        push_u8(&mut bytes, 1); // Type: Number
866        push_u8(&mut bytes, 1); // Sub-type: i64
867        push_i64(&mut bytes, -123456789);
868
869        let result = deser(bytes).expect("should deserialize i64");
870        assert_eq!(
871            result.0,
872            Value::Number(Number::from(-123456789i64))
873        );
874    }
875
876    // Tests push_i64: handles boundary values (MIN/MAX)
877    #[test]
878    fn accepts_i64_min_max_values() {
879        let mut bytes_min = Vec::new();
880        push_u8(&mut bytes_min, 1); // Type: Number
881        push_u8(&mut bytes_min, 1); // Sub-type: i64
882        push_i64(&mut bytes_min, i64::MIN);
883
884        let result_min = deser(bytes_min).expect("should deserialize i64::MIN");
885        assert_eq!(result_min.0, Value::Number(Number::from(i64::MIN)));
886
887        let mut bytes_max = Vec::new();
888        push_u8(&mut bytes_max, 1); // Type: Number
889        push_u8(&mut bytes_max, 1); // Sub-type: i64
890        push_i64(&mut bytes_max, i64::MAX);
891
892        let result_max = deser(bytes_max).expect("should deserialize i64::MAX");
893        assert_eq!(result_max.0, Value::Number(Number::from(i64::MAX)));
894    }
895
896    // Tests push_i64: handles zero, positive, and negative values
897    #[test]
898    fn accepts_i64_zero_positive_negative() {
899        let mut bytes_zero = Vec::new();
900        push_u8(&mut bytes_zero, 1);
901        push_u8(&mut bytes_zero, 1);
902        push_i64(&mut bytes_zero, 0);
903        let result_zero = deser(bytes_zero).expect("should deserialize 0");
904        assert_eq!(result_zero.0, Value::Number(Number::from(0i64)));
905
906        let mut bytes_pos = Vec::new();
907        push_u8(&mut bytes_pos, 1);
908        push_u8(&mut bytes_pos, 1);
909        push_i64(&mut bytes_pos, 42);
910        let result_pos = deser(bytes_pos).expect("should deserialize positive");
911        assert_eq!(result_pos.0, Value::Number(Number::from(42i64)));
912
913        let mut bytes_neg = Vec::new();
914        push_u8(&mut bytes_neg, 1);
915        push_u8(&mut bytes_neg, 1);
916        push_i64(&mut bytes_neg, -42);
917        let result_neg = deser(bytes_neg).expect("should deserialize negative");
918        assert_eq!(result_neg.0, Value::Number(Number::from(-42i64)));
919    }
920
921    // Tests push_u64: serializes unsigned integers correctly
922    #[test]
923    fn accepts_u64_number_via_push_u64() {
924        let mut bytes = Vec::new();
925        push_u8(&mut bytes, 1); // Type: Number
926        push_u8(&mut bytes, 2); // Sub-type: u64
927        push_u64(&mut bytes, 987654321);
928
929        let result = deser(bytes).expect("should deserialize u64");
930        assert_eq!(
931            result.0,
932            Value::Number(Number::from(987654321u64))
933        );
934    }
935
936    // Tests push_u64: handles boundary values (MIN=0, MAX)
937    #[test]
938    fn accepts_u64_min_max_values() {
939        let mut bytes_min = Vec::new();
940        push_u8(&mut bytes_min, 1); // Type: Number
941        push_u8(&mut bytes_min, 2); // Sub-type: u64
942        push_u64(&mut bytes_min, u64::MIN);
943
944        let result_min = deser(bytes_min).expect("should deserialize u64::MIN");
945        assert_eq!(result_min.0, Value::Number(Number::from(u64::MIN)));
946
947        let mut bytes_max = Vec::new();
948        push_u8(&mut bytes_max, 1); // Type: Number
949        push_u8(&mut bytes_max, 2); // Sub-type: u64
950        push_u64(&mut bytes_max, u64::MAX);
951
952        let result_max = deser(bytes_max).expect("should deserialize u64::MAX");
953        assert_eq!(result_max.0, Value::Number(Number::from(u64::MAX)));
954    }
955
956    // Tests push_f64: serializes floating point numbers correctly
957    #[test]
958    fn accepts_f64_number_via_push_f64() {
959        let mut bytes = Vec::new();
960        push_u8(&mut bytes, 1); // Type: Number
961        push_u8(&mut bytes, 0); // Sub-type: f64
962        push_f64(&mut bytes, 3.14159);
963
964        let result = deser(bytes).expect("should deserialize f64");
965        assert_eq!(
966            result.0,
967            Value::Number(Number::from_f64(3.14159).unwrap())
968        );
969    }
970
971    // Tests push_f64: handles special values (+0, -0, very large/small)
972    #[test]
973    fn accepts_f64_special_values() {
974        let mut bytes_pos_zero = Vec::new();
975        push_u8(&mut bytes_pos_zero, 1);
976        push_u8(&mut bytes_pos_zero, 0);
977        push_f64(&mut bytes_pos_zero, 0.0);
978        let result = deser(bytes_pos_zero).expect("should deserialize +0.0");
979        assert_eq!(result.0, Value::Number(Number::from_f64(0.0).unwrap()));
980
981        let mut bytes_neg_zero = Vec::new();
982        push_u8(&mut bytes_neg_zero, 1);
983        push_u8(&mut bytes_neg_zero, 0);
984        push_f64(&mut bytes_neg_zero, -0.0);
985        let result = deser(bytes_neg_zero).expect("should deserialize -0.0");
986        assert_eq!(result.0, Value::Number(Number::from_f64(-0.0).unwrap()));
987
988        let mut bytes_large = Vec::new();
989        push_u8(&mut bytes_large, 1);
990        push_u8(&mut bytes_large, 0);
991        push_f64(&mut bytes_large, 1.7976931348623157e308);
992        let result = deser(bytes_large).expect("should deserialize large f64");
993        assert!(result.0.is_number());
994
995        let mut bytes_small = Vec::new();
996        push_u8(&mut bytes_small, 1);
997        push_u8(&mut bytes_small, 0);
998        push_f64(&mut bytes_small, -2.2250738585072014e-308);
999        let result = deser(bytes_small).expect("should deserialize small negative f64");
1000        assert!(result.0.is_number());
1001    }
1002
1003    // Duplicate object keys: last value wins (semantic note: not ideal but accepted)
1004    #[test]
1005    fn accepts_but_overwrites_duplicate_object_keys_semantic_issue() {
1006        let mut bytes = Vec::new();
1007        push_u8(&mut bytes, 4); // Object
1008        push_u32(&mut bytes, 2); // 2 pairs
1009
1010        push_borsh_string(&mut bytes, "a");
1011        push_u8(&mut bytes, 1); // Number
1012        push_u8(&mut bytes, 2); // u64
1013        push_u64(&mut bytes, 1);
1014
1015        push_borsh_string(&mut bytes, "a"); // duplicate key
1016        push_u8(&mut bytes, 1); // Number
1017        push_u8(&mut bytes, 2); // u64
1018        push_u64(&mut bytes, 2);
1019
1020        let v = deser(bytes).expect("should deserialize");
1021        match v.0 {
1022            serde_json::Value::Object(map) => {
1023                assert_eq!(
1024                    map.get("a").unwrap(),
1025                    &serde_json::Value::Number(serde_json::Number::from(2u64))
1026                );
1027            }
1028            _ => panic!("expected object"),
1029        }
1030    }
1031}