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