1use crate::value_map::ValueMap;
2use crate::{Error, Value};
3use base64::prelude::BASE64_STANDARD;
4use base64::Engine;
5use serde_json::{Map, Number, Value as JsonValue};
6use std::collections::BTreeMap;
7
8impl Value {
9 pub fn convert_from_serde_json_map<I, R>(map: I) -> R
10 where
11 I: IntoIterator<Item = (String, JsonValue)>,
12 R: FromIterator<(String, Value)>,
13 {
14 map.into_iter()
15 .map(|(key, serde_json_value)| (key, serde_json_value.into()))
16 .collect()
17 }
18
19 pub fn try_into_validating_json(self) -> Result<JsonValue, Error> {
20 Ok(match self {
21 Value::U128(i) => {
22 if i > u64::MAX as u128 {
23 return Err(Error::IntegerSizeError);
24 }
25 JsonValue::Number((i as u64).into())
26 }
27 Value::I128(i) => {
28 if i > i64::MAX as i128 {
29 return Err(Error::IntegerSizeError);
30 }
31 if i < i64::MIN as i128 {
32 return Err(Error::IntegerSizeError);
33 }
34 JsonValue::Number((i as i64).into())
35 }
36 Value::U64(i) => JsonValue::Number(i.into()),
37 Value::I64(i) => JsonValue::Number(i.into()),
38 Value::U32(i) => JsonValue::Number(i.into()),
39 Value::I32(i) => JsonValue::Number(i.into()),
40 Value::U16(i) => JsonValue::Number(i.into()),
41 Value::I16(i) => JsonValue::Number(i.into()),
42 Value::U8(i) => JsonValue::Number(i.into()),
43 Value::I8(i) => JsonValue::Number(i.into()),
44 Value::Float(float) => JsonValue::Number(Number::from_f64(float).ok_or_else(|| {
48 Error::Unsupported("non-finite float (NaN/±∞) is not representable in JSON".into())
49 })?),
50 Value::Text(string) => JsonValue::String(string),
51 Value::Bool(value) => JsonValue::Bool(value),
52 Value::Null => JsonValue::Null,
53 Value::Array(array) => JsonValue::Array(
54 array
55 .into_iter()
56 .map(|value| value.try_into_validating_json())
57 .collect::<Result<Vec<JsonValue>, Error>>()?,
58 ),
59 Value::Map(map) => JsonValue::Object(
60 map.into_iter()
61 .map(|(k, v)| {
62 let string = k.into_text()?;
63 Ok((string, v.try_into_validating_json()?))
64 })
65 .collect::<Result<Map<String, JsonValue>, Error>>()?,
66 ),
67 Value::Identifier(bytes) => {
68 JsonValue::Array(
70 bytes
71 .into_iter()
72 .map(|a| JsonValue::Number(a.into()))
73 .collect(),
74 )
75 }
76 Value::Bytes(bytes) => JsonValue::Array(
77 bytes
78 .into_iter()
79 .map(|byte| JsonValue::Number(byte.into()))
80 .collect(),
81 ),
82 Value::Bytes20(bytes) => JsonValue::Array(
83 bytes
84 .into_iter()
85 .map(|byte| JsonValue::Number(byte.into()))
86 .collect(),
87 ),
88 Value::Bytes32(bytes) => JsonValue::Array(
89 bytes
90 .into_iter()
91 .map(|byte| JsonValue::Number(byte.into()))
92 .collect(),
93 ),
94 Value::Bytes36(bytes) => JsonValue::Array(
95 bytes
96 .into_iter()
97 .map(|byte| JsonValue::Number(byte.into()))
98 .collect(),
99 ),
100 Value::EnumU8(_) => {
101 return Err(Error::Unsupported(
102 "No support for conversion of EnumU8 to JSONValue".to_string(),
103 ))
104 }
105 Value::EnumString(_) => {
106 return Err(Error::Unsupported(
107 "No support for conversion of EnumString to JSONValue".to_string(),
108 ))
109 }
110 })
111 }
112
113 pub fn try_into_validating_btree_map_json(self) -> Result<BTreeMap<String, JsonValue>, Error> {
114 self.into_btree_string_map()?
115 .into_iter()
116 .map(|(key, value)| Ok((key, value.try_into_validating_json()?)))
117 .collect()
118 }
119
120 pub fn try_to_validating_json(&self) -> Result<JsonValue, Error> {
121 Ok(match self {
122 Value::U128(i) => {
123 if *i > u64::MAX as u128 {
124 return Err(Error::IntegerSizeError);
125 }
126 JsonValue::Number((*i as u64).into())
127 }
128 Value::I128(i) => {
129 if *i > i64::MAX as i128 {
130 return Err(Error::IntegerSizeError);
131 }
132 if *i < i64::MIN as i128 {
133 return Err(Error::IntegerSizeError);
134 }
135 JsonValue::Number((*i as i64).into())
136 }
137 Value::U64(i) => JsonValue::Number((*i).into()),
138 Value::I64(i) => JsonValue::Number((*i).into()),
139 Value::U32(i) => JsonValue::Number((*i).into()),
140 Value::I32(i) => JsonValue::Number((*i).into()),
141 Value::U16(i) => JsonValue::Number((*i).into()),
142 Value::I16(i) => JsonValue::Number((*i).into()),
143 Value::U8(i) => JsonValue::Number((*i).into()),
144 Value::I8(i) => JsonValue::Number((*i).into()),
145 Value::Float(float) => {
147 JsonValue::Number(Number::from_f64(*float).ok_or_else(|| {
148 Error::Unsupported(
149 "non-finite float (NaN/±∞) is not representable in JSON".into(),
150 )
151 })?)
152 }
153 Value::Text(string) => JsonValue::String(string.clone()),
154 Value::Bool(value) => JsonValue::Bool(*value),
155 Value::Null => JsonValue::Null,
156 Value::Array(array) => JsonValue::Array(
157 array
158 .iter()
159 .map(|value| value.try_to_validating_json())
160 .collect::<Result<Vec<JsonValue>, Error>>()?,
161 ),
162 Value::Map(map) => JsonValue::Object(
163 map.iter()
164 .map(|(k, v)| {
165 let string = k.to_text()?;
166 Ok((string, v.try_to_validating_json()?))
167 })
168 .collect::<Result<Map<String, JsonValue>, Error>>()?,
169 ),
170 Value::Identifier(bytes) => {
171 JsonValue::Array(
173 bytes
174 .iter()
175 .map(|a| JsonValue::Number((*a).into()))
176 .collect(),
177 )
178 }
179 Value::Bytes(bytes) => JsonValue::Array(
180 bytes
181 .iter()
182 .map(|byte| JsonValue::Number((*byte).into()))
183 .collect(),
184 ),
185 Value::Bytes20(bytes) => JsonValue::Array(
186 bytes
187 .iter()
188 .map(|byte| JsonValue::Number((*byte).into()))
189 .collect(),
190 ),
191 Value::Bytes32(bytes) => JsonValue::Array(
192 bytes
193 .iter()
194 .map(|byte| JsonValue::Number((*byte).into()))
195 .collect(),
196 ),
197 Value::Bytes36(bytes) => JsonValue::Array(
198 bytes
199 .iter()
200 .map(|byte| JsonValue::Number((*byte).into()))
201 .collect(),
202 ),
203 Value::EnumU8(_) => {
204 return Err(Error::Unsupported(
205 "No support for conversion of EnumU8 to JSONValue".to_string(),
206 ))
207 }
208 Value::EnumString(_) => {
209 return Err(Error::Unsupported(
210 "No support for conversion of EnumString to JSONValue".to_string(),
211 ))
212 }
213 })
214 }
215}
216
217impl From<JsonValue> for Value {
218 fn from(value: JsonValue) -> Self {
219 match value {
220 JsonValue::Null => Self::Null,
221 JsonValue::Bool(value) => Self::Bool(value),
222 JsonValue::Number(number) => {
223 if let Some(value) = number.as_u64() {
224 return Self::U64(value);
225 } else if let Some(value) = number.as_i64() {
226 return Self::I64(value);
227 } else if let Some(value) = number.as_f64() {
228 return Self::Float(value);
229 }
230 unreachable!("this shouldn't be reachable")
231 }
232 JsonValue::String(string) => Self::Text(string),
233 JsonValue::Array(array) => {
234 Self::Array(array.into_iter().map(|v| v.into()).collect())
244 }
245 JsonValue::Object(map) => {
246 Self::Map(map.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
247 }
248 }
249 }
250}
251
252impl From<&JsonValue> for Value {
253 fn from(value: &JsonValue) -> Self {
254 match value {
255 JsonValue::Null => Self::Null,
256 JsonValue::Bool(value) => Self::Bool(*value),
257 JsonValue::Number(number) => {
258 if let Some(value) = number.as_u64() {
259 return Self::U64(value);
260 } else if let Some(value) = number.as_i64() {
261 return Self::I64(value);
262 } else if let Some(value) = number.as_f64() {
263 return Self::Float(value);
264 }
265 unreachable!("this shouldn't be reachable")
266 }
267 JsonValue::String(string) => Self::Text(string.clone()),
268 JsonValue::Array(array) => {
269 Self::Array(array.iter().map(|v| v.into()).collect())
271 }
272 JsonValue::Object(map) => Self::Map(
273 map.into_iter()
274 .map(|(k, v)| (k.clone().into(), v.into()))
275 .collect(),
276 ),
277 }
278 }
279}
280
281impl TryInto<JsonValue> for Value {
282 type Error = Error;
283
284 fn try_into(self) -> Result<JsonValue, Self::Error> {
285 Ok(match self {
286 Value::U128(i) => JsonValue::String(i.to_string()),
288 Value::I128(i) => JsonValue::String(i.to_string()),
289 Value::U64(i) => JsonValue::Number(i.into()),
290 Value::I64(i) => JsonValue::Number(i.into()),
291 Value::U32(i) => JsonValue::Number(i.into()),
292 Value::I32(i) => JsonValue::Number(i.into()),
293 Value::U16(i) => JsonValue::Number(i.into()),
294 Value::I16(i) => JsonValue::Number(i.into()),
295 Value::U8(i) => JsonValue::Number(i.into()),
296 Value::I8(i) => JsonValue::Number(i.into()),
297 Value::Bytes(bytes) => JsonValue::String(BASE64_STANDARD.encode(bytes.as_slice())),
298 Value::Bytes20(bytes) => JsonValue::String(BASE64_STANDARD.encode(bytes.as_slice())),
299 Value::Bytes32(bytes) => JsonValue::String(BASE64_STANDARD.encode(bytes.as_slice())),
300 Value::Bytes36(bytes) => JsonValue::String(BASE64_STANDARD.encode(bytes.as_slice())),
301 Value::Float(float) => JsonValue::Number(Number::from_f64(float).ok_or_else(|| {
303 Error::Unsupported("non-finite float (NaN/±∞) is not representable in JSON".into())
304 })?),
305 Value::Text(string) => JsonValue::String(string),
306 Value::Bool(value) => JsonValue::Bool(value),
307 Value::Null => JsonValue::Null,
308 Value::Array(array) => JsonValue::Array(
309 array
310 .into_iter()
311 .map(|value| value.try_into())
312 .collect::<Result<Vec<JsonValue>, Error>>()?,
313 ),
314 Value::Map(map) => JsonValue::Object(
315 map.into_iter()
316 .map(|(k, v)| {
317 let string = k.into_text()?;
318 Ok((string, v.try_into()?))
319 })
320 .collect::<Result<Map<String, JsonValue>, Error>>()?,
321 ),
322 Value::Identifier(bytes) => {
323 JsonValue::String(bs58::encode(bytes.as_slice()).into_string())
324 }
325 Value::EnumU8(_) => {
326 return Err(Error::Unsupported(
327 "No support for conversion of EnumU8 to JSONValue".to_string(),
328 ))
329 }
330 Value::EnumString(_) => {
331 return Err(Error::Unsupported(
332 "No support for conversion of EnumString to JSONValue".to_string(),
333 ))
334 }
335 })
336 }
337}
338
339pub trait BTreeValueJsonConverter {
340 fn into_json_value(self) -> Result<JsonValue, Error>;
341 fn into_validating_json_value(self) -> Result<JsonValue, Error>;
342 fn to_json_value(&self) -> Result<JsonValue, Error>;
343 fn to_validating_json_value(&self) -> Result<JsonValue, Error>;
344 fn from_json_value(value: JsonValue) -> Result<Self, Error>
345 where
346 Self: Sized;
347}
348
349impl BTreeValueJsonConverter for BTreeMap<String, Value> {
350 fn into_json_value(self) -> Result<JsonValue, Error> {
351 Ok(JsonValue::Object(
352 self.into_iter()
353 .map(|(key, value)| Ok((key, value.try_into()?)))
354 .collect::<Result<Map<String, JsonValue>, Error>>()?,
355 ))
356 }
357
358 fn into_validating_json_value(self) -> Result<JsonValue, Error> {
359 Ok(JsonValue::Object(
360 self.into_iter()
361 .map(|(key, value)| Ok((key, value.try_into_validating_json()?)))
362 .collect::<Result<Map<String, JsonValue>, Error>>()?,
363 ))
364 }
365
366 fn to_json_value(&self) -> Result<JsonValue, Error> {
367 Ok(JsonValue::Object(
368 self.iter()
369 .map(|(key, value)| Ok((key.clone(), value.clone().try_into()?)))
370 .collect::<Result<Map<String, JsonValue>, Error>>()?,
371 ))
372 }
373
374 fn to_validating_json_value(&self) -> Result<JsonValue, Error> {
375 Ok(JsonValue::Object(
376 self.iter()
377 .map(|(key, value)| Ok((key.to_owned(), value.try_to_validating_json()?)))
378 .collect::<Result<Map<String, JsonValue>, Error>>()?,
379 ))
380 }
381
382 fn from_json_value(value: JsonValue) -> Result<Self, Error> {
383 let platform_value: Value = value.into();
384 platform_value.into_btree_string_map()
385 }
386}
387
388impl From<BTreeMap<String, JsonValue>> for Value {
389 fn from(value: BTreeMap<String, JsonValue>) -> Self {
390 let map: ValueMap = value
391 .into_iter()
392 .map(|(key, json_value)| {
393 let value: Value = json_value.into();
394 (Value::Text(key), value)
395 })
396 .collect();
397 Value::Map(map)
398 }
399}
400
401impl From<&BTreeMap<String, JsonValue>> for Value {
402 fn from(value: &BTreeMap<String, JsonValue>) -> Self {
403 let map: ValueMap = value
404 .iter()
405 .map(|(key, json_value)| {
406 let value: Value = json_value.into();
407 (Value::Text(key.clone()), value)
408 })
409 .collect();
410 Value::Map(map)
411 }
412}
413
414#[cfg(test)]
415#[allow(clippy::approx_constant)]
416mod tests {
417 use crate::converter::serde_json::BTreeValueJsonConverter;
418 use crate::{Error, Value};
419 use base64::prelude::BASE64_STANDARD;
420 use base64::Engine;
421 use serde_json::{json, Value as JsonValue};
422 use std::collections::BTreeMap;
423
424 #[test]
425 fn test_json_array() {
426 let json = json!({
427 "type": 5,
428 "protocolVersion": 1,
429 "revision": 0,
430 "signature": "HxtcTSpRdACokorvpx/f4ezM40e0WtgW2GUvjiwNkHPwKDppkIoS2cirhqpZURlhDuYdu+E0KllbHNlYghcK9Bg=",
431 "signaturePublicKeyId": 1,
432 "addPublicKeys": [
433 {
434 "id": 0,
435 "purpose": 0,
436 "securityLevel": 0,
437 "type": 0,
438 "data": "Aya0WP8EhKQ6Dq+51sAnqdPah664X9CUciVJYAfvfTnX",
439 "readOnly": false,
440 "signature": "HxtcTSpRdACokorvpx/f4ezM40e0WtgW2GUvjiwNkHPwKDppkIoS2cirhqpZURlhDuYdu+E0KllbHNlYghcK9Bg="
441 }
442 ],
443 "disablePublicKeys": [ 0 ],
444 "identityId": "62DHhTfZV3NvUbXUha1mavLqSEy2GaWYja2qeTYNUhk"
445 });
446
447 let value: Value = json.into();
448 let array = value
449 .get_optional_array_slice("addPublicKeys")
450 .expect("expected to get array slice")
451 .unwrap();
452 assert_eq!(array.len(), 1);
453 assert!(array.first().unwrap().is_map());
454 let array = value
455 .get_optional_array_slice("disablePublicKeys")
456 .expect("expected to get array slice")
457 .unwrap();
458 assert_eq!(array.len(), 1);
459 }
460
461 #[test]
466 fn validating_json_null() {
467 let result = Value::Null.try_into_validating_json().unwrap();
468 assert_eq!(result, JsonValue::Null);
469 }
470
471 #[test]
472 fn validating_json_bool() {
473 assert_eq!(
474 Value::Bool(true).try_into_validating_json().unwrap(),
475 JsonValue::Bool(true)
476 );
477 assert_eq!(
478 Value::Bool(false).try_into_validating_json().unwrap(),
479 JsonValue::Bool(false)
480 );
481 }
482
483 #[test]
484 fn validating_json_u8() {
485 let result = Value::U8(42).try_into_validating_json().unwrap();
486 assert_eq!(result, json!(42));
487 }
488
489 #[test]
490 fn validating_json_i8() {
491 let result = Value::I8(-5).try_into_validating_json().unwrap();
492 assert_eq!(result, json!(-5));
493 }
494
495 #[test]
496 fn validating_json_u16() {
497 let result = Value::U16(1000).try_into_validating_json().unwrap();
498 assert_eq!(result, json!(1000));
499 }
500
501 #[test]
502 fn validating_json_i16() {
503 let result = Value::I16(-1000).try_into_validating_json().unwrap();
504 assert_eq!(result, json!(-1000));
505 }
506
507 #[test]
508 fn validating_json_u32() {
509 let result = Value::U32(100_000).try_into_validating_json().unwrap();
510 assert_eq!(result, json!(100_000));
511 }
512
513 #[test]
514 fn validating_json_i32() {
515 let result = Value::I32(-100_000).try_into_validating_json().unwrap();
516 assert_eq!(result, json!(-100_000));
517 }
518
519 #[test]
520 fn validating_json_u64() {
521 let result = Value::U64(u64::MAX).try_into_validating_json().unwrap();
522 assert_eq!(result, json!(u64::MAX));
523 }
524
525 #[test]
526 fn validating_json_i64() {
527 let result = Value::I64(i64::MIN).try_into_validating_json().unwrap();
528 assert_eq!(result, json!(i64::MIN));
529 }
530
531 #[test]
532 fn validating_json_float() {
533 let result = Value::Float(3.14).try_into_validating_json().unwrap();
534 assert_eq!(result, json!(3.14));
535 }
536
537 #[test]
538 fn validating_json_text() {
539 let result = Value::Text("hello".into())
540 .try_into_validating_json()
541 .unwrap();
542 assert_eq!(result, json!("hello"));
543 }
544
545 #[test]
546 fn validating_json_u128_fits_u64() {
547 let val = u64::MAX as u128;
548 let result = Value::U128(val).try_into_validating_json().unwrap();
549 assert_eq!(result, json!(u64::MAX));
550 }
551
552 #[test]
553 fn validating_json_u128_too_large() {
554 let val = u64::MAX as u128 + 1;
555 let err = Value::U128(val).try_into_validating_json().unwrap_err();
556 assert_eq!(err, Error::IntegerSizeError);
557 }
558
559 #[test]
560 fn validating_json_i128_fits_i64_positive() {
561 let val = i64::MAX as i128;
562 let result = Value::I128(val).try_into_validating_json().unwrap();
563 assert_eq!(result, json!(i64::MAX));
564 }
565
566 #[test]
567 fn validating_json_i128_fits_i64_negative() {
568 let val = i64::MIN as i128;
569 let result = Value::I128(val).try_into_validating_json().unwrap();
570 assert_eq!(result, json!(i64::MIN));
571 }
572
573 #[test]
574 fn validating_json_i128_too_large_positive() {
575 let val = i64::MAX as i128 + 1;
576 let err = Value::I128(val).try_into_validating_json().unwrap_err();
577 assert_eq!(err, Error::IntegerSizeError);
578 }
579
580 #[test]
581 fn validating_json_i128_too_small_negative() {
582 let val = i64::MIN as i128 - 1;
583 let err = Value::I128(val).try_into_validating_json().unwrap_err();
584 assert_eq!(err, Error::IntegerSizeError);
585 }
586
587 #[test]
588 fn validating_json_bytes() {
589 let result = Value::Bytes(vec![1, 2, 3])
590 .try_into_validating_json()
591 .unwrap();
592 assert_eq!(result, json!([1, 2, 3]));
593 }
594
595 #[test]
596 fn validating_json_bytes20() {
597 let bytes = [7u8; 20];
598 let result = Value::Bytes20(bytes).try_into_validating_json().unwrap();
599 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
600 assert_eq!(result, JsonValue::Array(arr));
601 }
602
603 #[test]
604 fn validating_json_bytes32() {
605 let bytes = [9u8; 32];
606 let result = Value::Bytes32(bytes).try_into_validating_json().unwrap();
607 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
608 assert_eq!(result, JsonValue::Array(arr));
609 }
610
611 #[test]
612 fn validating_json_bytes36() {
613 let bytes = [11u8; 36];
614 let result = Value::Bytes36(bytes).try_into_validating_json().unwrap();
615 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
616 assert_eq!(result, JsonValue::Array(arr));
617 }
618
619 #[test]
620 fn validating_json_identifier() {
621 let bytes = [0xABu8; 32];
622 let result = Value::Identifier(bytes).try_into_validating_json().unwrap();
623 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
624 assert_eq!(result, JsonValue::Array(arr));
625 }
626
627 #[test]
628 fn validating_json_array_nested() {
629 let val = Value::Array(vec![Value::U64(1), Value::Text("two".into())]);
630 let result = val.try_into_validating_json().unwrap();
631 assert_eq!(result, json!([1, "two"]));
632 }
633
634 #[test]
635 fn validating_json_map() {
636 let map = vec![
637 (Value::Text("a".into()), Value::U64(1)),
638 (Value::Text("b".into()), Value::Bool(true)),
639 ];
640 let val = Value::Map(map);
641 let result = val.try_into_validating_json().unwrap();
642 assert_eq!(result, json!({"a": 1, "b": true}));
643 }
644
645 #[test]
646 fn validating_json_enum_u8_unsupported() {
647 let err = Value::EnumU8(vec![1, 2])
648 .try_into_validating_json()
649 .unwrap_err();
650 assert!(matches!(err, Error::Unsupported(_)));
651 }
652
653 #[test]
654 fn validating_json_enum_string_unsupported() {
655 let err = Value::EnumString(vec!["a".into()])
656 .try_into_validating_json()
657 .unwrap_err();
658 assert!(matches!(err, Error::Unsupported(_)));
659 }
660
661 #[test]
666 fn from_json_null() {
667 let val: Value = JsonValue::Null.into();
668 assert_eq!(val, Value::Null);
669 }
670
671 #[test]
672 fn from_json_bool_true() {
673 let val: Value = json!(true).into();
674 assert_eq!(val, Value::Bool(true));
675 }
676
677 #[test]
678 fn from_json_bool_false() {
679 let val: Value = json!(false).into();
680 assert_eq!(val, Value::Bool(false));
681 }
682
683 #[test]
684 fn from_json_positive_integer() {
685 let val: Value = json!(42).into();
686 assert_eq!(val, Value::U64(42));
687 }
688
689 #[test]
690 fn from_json_negative_integer() {
691 let val: Value = json!(-7).into();
692 assert_eq!(val, Value::I64(-7));
693 }
694
695 #[test]
696 fn from_json_float() {
697 let val: Value = json!(2.5).into();
698 assert_eq!(val, Value::Float(2.5));
699 }
700
701 #[test]
702 fn from_json_string() {
703 let val: Value = json!("hello").into();
704 assert_eq!(val, Value::Text("hello".into()));
705 }
706
707 #[test]
708 fn from_json_object() {
709 let val: Value = json!({"key": "value"}).into();
710 assert!(val.is_map());
711 }
712
713 #[test]
724 fn from_json_array_10_u8_range_stays_array_not_bytes() {
725 let arr: Vec<JsonValue> = (0u64..10).map(|i| json!(i)).collect();
728 let val: Value = JsonValue::Array(arr).into();
729 assert_eq!(
730 val,
731 Value::Array(vec![
732 Value::U64(0),
733 Value::U64(1),
734 Value::U64(2),
735 Value::U64(3),
736 Value::U64(4),
737 Value::U64(5),
738 Value::U64(6),
739 Value::U64(7),
740 Value::U64(8),
741 Value::U64(9),
742 ])
743 );
744 }
745
746 #[test]
747 fn from_json_array_9_u8_range_stays_array() {
748 let arr: Vec<JsonValue> = (0u64..9).map(|i| json!(i)).collect();
749 let val: Value = JsonValue::Array(arr).into();
750 assert!(matches!(val, Value::Array(_)));
751 }
752
753 #[test]
754 fn from_json_array_mixed_types_stays_array() {
755 let mut arr: Vec<JsonValue> = (0u64..10).map(|i| json!(i)).collect();
756 arr.push(json!("not_a_number"));
757 let val: Value = JsonValue::Array(arr).into();
758 assert!(matches!(val, Value::Array(_)));
759 }
760
761 #[test]
762 fn from_json_array_large_values_stays_array() {
763 let arr: Vec<JsonValue> = (0u64..12).map(|i| json!(i * 100)).collect();
764 let val: Value = JsonValue::Array(arr).into();
765 assert!(matches!(val, Value::Array(_)));
766 }
767
768 #[test]
769 fn from_json_array_all_255_stays_array_not_bytes() {
770 let arr: Vec<JsonValue> = vec![json!(255); 10];
773 let val: Value = JsonValue::Array(arr).into();
774 assert_eq!(val, Value::Array(vec![Value::U64(255); 10]));
775 }
776
777 #[test]
778 fn from_json_array_with_negative_stays_array() {
779 let mut arr: Vec<JsonValue> = (0u64..9).map(|i| json!(i)).collect();
780 arr.push(json!(-1));
781 let val: Value = JsonValue::Array(arr).into();
782 assert!(matches!(val, Value::Array(_)));
783 }
784
785 #[test]
786 fn from_json_long_byte_like_array_stays_array_not_bytes() {
787 let original: JsonValue = JsonValue::Array(vec![json!(7u64); 1000]);
794 let value: Value = original.clone().into();
795 assert!(
796 matches!(value, Value::Array(_)),
797 "1000-element u8-range JSON array must stay an array, not silently \
798 become bytes"
799 );
800 let recovered: JsonValue = value.try_into().unwrap();
801 assert_eq!(original, recovered, "round-trip JSON array → Value → JSON");
802 }
803
804 #[test]
809 fn from_json_ref_null() {
810 let jv = JsonValue::Null;
811 let val: Value = (&jv).into();
812 assert_eq!(val, Value::Null);
813 }
814
815 #[test]
816 fn from_json_ref_array_stays_array_not_bytes() {
817 let arr: Vec<JsonValue> = (0u64..15).map(|i| json!(i)).collect();
821 let jv = JsonValue::Array(arr);
822 let val: Value = (&jv).into();
823 assert!(matches!(val, Value::Array(_)));
824 }
825
826 #[test]
827 fn from_json_ref_array_short_stays_array() {
828 let arr: Vec<JsonValue> = (0u64..5).map(|i| json!(i)).collect();
829 let jv = JsonValue::Array(arr);
830 let val: Value = (&jv).into();
831 assert!(matches!(val, Value::Array(_)));
832 }
833
834 #[test]
839 fn try_into_json_bytes_become_base64() {
840 let bytes = vec![0xDE, 0xAD, 0xBE, 0xEF];
841 let expected = BASE64_STANDARD.encode(&bytes);
842 let result: JsonValue = Value::Bytes(bytes).try_into().unwrap();
843 assert_eq!(result, JsonValue::String(expected));
844 }
845
846 #[test]
847 fn try_into_json_bytes20_become_base64() {
848 let bytes = [0xAAu8; 20];
849 let expected = BASE64_STANDARD.encode(bytes);
850 let result: JsonValue = Value::Bytes20(bytes).try_into().unwrap();
851 assert_eq!(result, JsonValue::String(expected));
852 }
853
854 #[test]
855 fn try_into_json_bytes32_become_base64() {
856 let bytes = [0xBBu8; 32];
857 let expected = BASE64_STANDARD.encode(bytes);
858 let result: JsonValue = Value::Bytes32(bytes).try_into().unwrap();
859 assert_eq!(result, JsonValue::String(expected));
860 }
861
862 #[test]
863 fn try_into_json_bytes36_become_base64() {
864 let bytes = [0xCCu8; 36];
865 let expected = BASE64_STANDARD.encode(bytes);
866 let result: JsonValue = Value::Bytes36(bytes).try_into().unwrap();
867 assert_eq!(result, JsonValue::String(expected));
868 }
869
870 #[test]
871 fn try_into_json_identifier_becomes_bs58() {
872 let bytes = [0x01u8; 32];
873 let expected = bs58::encode(&bytes).into_string();
874 let result: JsonValue = Value::Identifier(bytes).try_into().unwrap();
875 assert_eq!(result, JsonValue::String(expected));
876 }
877
878 #[test]
879 fn try_into_json_u128_becomes_string() {
880 let result: JsonValue = Value::U128(u128::MAX).try_into().unwrap();
881 assert_eq!(result, JsonValue::String(u128::MAX.to_string()));
882 }
883
884 #[test]
885 fn try_into_json_i128_becomes_string() {
886 let result: JsonValue = Value::I128(i128::MIN).try_into().unwrap();
887 assert_eq!(result, JsonValue::String(i128::MIN.to_string()));
888 }
889
890 #[test]
891 fn try_into_json_null() {
892 let result: JsonValue = Value::Null.try_into().unwrap();
893 assert_eq!(result, JsonValue::Null);
894 }
895
896 #[test]
897 fn try_into_json_bool() {
898 let result: JsonValue = Value::Bool(true).try_into().unwrap();
899 assert_eq!(result, JsonValue::Bool(true));
900 }
901
902 #[test]
903 fn try_into_json_text() {
904 let result: JsonValue = Value::Text("abc".into()).try_into().unwrap();
905 assert_eq!(result, json!("abc"));
906 }
907
908 #[test]
909 fn try_into_json_integer_types() {
910 let r: JsonValue = Value::U8(1).try_into().unwrap();
911 assert_eq!(r, json!(1));
912 let r: JsonValue = Value::I8(-1).try_into().unwrap();
913 assert_eq!(r, json!(-1));
914 let r: JsonValue = Value::U16(500).try_into().unwrap();
915 assert_eq!(r, json!(500));
916 let r: JsonValue = Value::I16(-500).try_into().unwrap();
917 assert_eq!(r, json!(-500));
918 let r: JsonValue = Value::U32(70000).try_into().unwrap();
919 assert_eq!(r, json!(70000));
920 let r: JsonValue = Value::I32(-70000).try_into().unwrap();
921 assert_eq!(r, json!(-70000));
922 let r: JsonValue = Value::U64(123456789).try_into().unwrap();
923 assert_eq!(r, json!(123456789));
924 let r: JsonValue = Value::I64(-123456789).try_into().unwrap();
925 assert_eq!(r, json!(-123456789));
926 }
927
928 #[test]
929 fn try_into_json_array() {
930 let val = Value::Array(vec![Value::U64(1), Value::Bool(false)]);
931 let result: JsonValue = val.try_into().unwrap();
932 assert_eq!(result, json!([1, false]));
933 }
934
935 #[test]
936 fn try_into_json_map() {
937 let map = vec![(Value::Text("x".into()), Value::U64(99))];
938 let val = Value::Map(map);
939 let result: JsonValue = val.try_into().unwrap();
940 assert_eq!(result, json!({"x": 99}));
941 }
942
943 #[test]
944 fn try_into_json_enum_u8_error() {
945 let result: Result<JsonValue, Error> = Value::EnumU8(vec![1]).try_into();
946 assert!(matches!(result, Err(Error::Unsupported(_))));
947 }
948
949 #[test]
950 fn try_into_json_enum_string_error() {
951 let result: Result<JsonValue, Error> = Value::EnumString(vec!["a".into()]).try_into();
952 assert!(matches!(result, Err(Error::Unsupported(_))));
953 }
954
955 #[test]
960 fn round_trip_null() {
961 let original = Value::Null;
962 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
963 let back: Value = json.into();
964 assert_eq!(back, original);
965 }
966
967 #[test]
968 fn round_trip_bool() {
969 let original = Value::Bool(true);
970 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
971 let back: Value = json.into();
972 assert_eq!(back, Value::Bool(true));
973 }
974
975 #[test]
976 fn round_trip_u64() {
977 let original = Value::U64(42);
978 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
979 let back: Value = json.into();
980 assert_eq!(back, Value::U64(42));
982 }
983
984 #[test]
985 fn round_trip_i64() {
986 let original = Value::I64(-42);
987 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
988 let back: Value = json.into();
989 assert_eq!(back, Value::I64(-42));
990 }
991
992 #[test]
993 fn round_trip_text() {
994 let original = Value::Text("hello world".into());
995 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
996 let back: Value = json.into();
997 assert_eq!(back, original);
998 }
999
1000 #[test]
1005 fn btree_into_json_value() {
1006 let mut map = BTreeMap::new();
1007 map.insert("x".to_string(), Value::U64(10));
1008 map.insert("y".to_string(), Value::Text("test".into()));
1009 let json = map.into_json_value().unwrap();
1010 assert!(json.is_object());
1011 assert_eq!(json["x"], json!(10));
1012 assert_eq!(json["y"], json!("test"));
1013 }
1014
1015 #[test]
1016 fn btree_into_validating_json_value() {
1017 let mut map = BTreeMap::new();
1018 map.insert("n".to_string(), Value::U64(5));
1019 let json = map.into_validating_json_value().unwrap();
1020 assert_eq!(json["n"], json!(5));
1021 }
1022
1023 #[test]
1024 fn btree_to_json_value() {
1025 let mut map = BTreeMap::new();
1026 map.insert("k".to_string(), Value::Bool(true));
1027 let json = map.to_json_value().unwrap();
1028 assert_eq!(json["k"], json!(true));
1029 assert!(map.contains_key("k"));
1031 }
1032
1033 #[test]
1034 fn btree_to_validating_json_value() {
1035 let mut map = BTreeMap::new();
1036 map.insert("v".to_string(), Value::I64(-1));
1037 let json = map.to_validating_json_value().unwrap();
1038 assert_eq!(json["v"], json!(-1));
1039 }
1040
1041 #[test]
1042 fn btree_from_json_value() {
1043 let json = json!({"a": 1, "b": "two"});
1044 let map = BTreeMap::<String, Value>::from_json_value(json).unwrap();
1045 assert_eq!(map.get("a"), Some(&Value::U64(1)));
1046 assert_eq!(map.get("b"), Some(&Value::Text("two".into())));
1047 }
1048
1049 #[test]
1050 fn btree_from_json_value_non_object_error() {
1051 let json = json!([1, 2, 3]);
1052 let result = BTreeMap::<String, Value>::from_json_value(json);
1053 assert!(result.is_err());
1054 }
1055
1056 #[test]
1061 fn from_btree_json_map() {
1062 let mut btree = BTreeMap::new();
1063 btree.insert("key".to_string(), json!(42));
1064 let val: Value = btree.into();
1065 assert!(val.is_map());
1066 }
1067
1068 #[test]
1069 fn from_btree_json_map_ref() {
1070 let mut btree = BTreeMap::new();
1071 btree.insert("key".to_string(), json!(42));
1072 let val: Value = (&btree).into();
1073 assert!(val.is_map());
1074 }
1075
1076 #[test]
1081 fn try_to_validating_json_basic() {
1082 let val = Value::U64(99);
1083 let json = val.try_to_validating_json().unwrap();
1084 assert_eq!(json, json!(99));
1085 }
1086
1087 #[test]
1088 fn try_to_validating_json_u128_too_large() {
1089 let val = Value::U128(u128::MAX);
1090 let err = val.try_to_validating_json().unwrap_err();
1091 assert_eq!(err, Error::IntegerSizeError);
1092 }
1093
1094 #[test]
1095 fn try_to_validating_json_i128_too_large() {
1096 let val = Value::I128(i128::MAX);
1097 let err = val.try_to_validating_json().unwrap_err();
1098 assert_eq!(err, Error::IntegerSizeError);
1099 }
1100
1101 #[test]
1102 fn try_to_validating_json_i128_too_small() {
1103 let val = Value::I128(i128::MIN);
1104 let err = val.try_to_validating_json().unwrap_err();
1105 assert_eq!(err, Error::IntegerSizeError);
1106 }
1107
1108 #[test]
1109 fn try_to_validating_json_enum_u8_error() {
1110 let val = Value::EnumU8(vec![1]);
1111 let err = val.try_to_validating_json().unwrap_err();
1112 assert!(matches!(err, Error::Unsupported(_)));
1113 }
1114
1115 #[test]
1116 fn try_to_validating_json_enum_string_error() {
1117 let val = Value::EnumString(vec!["a".into()]);
1118 let err = val.try_to_validating_json().unwrap_err();
1119 assert!(matches!(err, Error::Unsupported(_)));
1120 }
1121
1122 #[test]
1127 fn try_into_validating_btree_map_json_success() {
1128 let map = vec![(Value::Text("k".into()), Value::U64(7))];
1129 let val = Value::Map(map);
1130 let result = val.try_into_validating_btree_map_json().unwrap();
1131 assert_eq!(result.get("k"), Some(&json!(7)));
1132 }
1133
1134 #[test]
1139 fn convert_from_serde_json_map_basic() {
1140 let pairs = vec![
1141 ("a".to_string(), json!(1)),
1142 ("b".to_string(), json!("hello")),
1143 ];
1144 let result: BTreeMap<String, Value> = Value::convert_from_serde_json_map(pairs);
1145 assert_eq!(result.get("a"), Some(&Value::U64(1)));
1146 assert_eq!(result.get("b"), Some(&Value::Text("hello".into())));
1147 }
1148
1149 #[test]
1150 fn non_finite_floats_error_in_all_three_json_converters() {
1151 for bad in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
1158 assert!(matches!(
1160 Value::Float(bad).try_into_validating_json(),
1161 Err(Error::Unsupported(_))
1162 ));
1163 assert!(matches!(
1165 Value::Float(bad).try_to_validating_json(),
1166 Err(Error::Unsupported(_))
1167 ));
1168 let plain: Result<JsonValue, Error> = Value::Float(bad).try_into();
1170 assert!(matches!(plain, Err(Error::Unsupported(_))));
1171 }
1172 assert_eq!(
1174 Value::Float(1.5).try_into_validating_json().unwrap(),
1175 json!(1.5)
1176 );
1177 }
1178}