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)]
425#[allow(clippy::approx_constant)]
426mod tests {
427 use crate::converter::serde_json::BTreeValueJsonConverter;
428 use crate::{Error, Value};
429 use base64::prelude::BASE64_STANDARD;
430 use base64::Engine;
431 use serde_json::{json, Value as JsonValue};
432 use std::collections::BTreeMap;
433
434 #[test]
435 fn test_json_array() {
436 let json = json!({
437 "type": 5,
438 "protocolVersion": 1,
439 "revision": 0,
440 "signature": "HxtcTSpRdACokorvpx/f4ezM40e0WtgW2GUvjiwNkHPwKDppkIoS2cirhqpZURlhDuYdu+E0KllbHNlYghcK9Bg=",
441 "signaturePublicKeyId": 1,
442 "addPublicKeys": [
443 {
444 "id": 0,
445 "purpose": 0,
446 "securityLevel": 0,
447 "type": 0,
448 "data": "Aya0WP8EhKQ6Dq+51sAnqdPah664X9CUciVJYAfvfTnX",
449 "readOnly": false,
450 "signature": "HxtcTSpRdACokorvpx/f4ezM40e0WtgW2GUvjiwNkHPwKDppkIoS2cirhqpZURlhDuYdu+E0KllbHNlYghcK9Bg="
451 }
452 ],
453 "disablePublicKeys": [ 0 ],
454 "identityId": "62DHhTfZV3NvUbXUha1mavLqSEy2GaWYja2qeTYNUhk"
455 });
456
457 let value: Value = json.into();
458 let array = value
459 .get_optional_array_slice("addPublicKeys")
460 .expect("expected to get array slice")
461 .unwrap();
462 assert_eq!(array.len(), 1);
463 assert!(array.first().unwrap().is_map());
464 let array = value
465 .get_optional_array_slice("disablePublicKeys")
466 .expect("expected to get array slice")
467 .unwrap();
468 assert_eq!(array.len(), 1);
469 }
470
471 #[test]
476 fn validating_json_null() {
477 let result = Value::Null.try_into_validating_json().unwrap();
478 assert_eq!(result, JsonValue::Null);
479 }
480
481 #[test]
482 fn validating_json_bool() {
483 assert_eq!(
484 Value::Bool(true).try_into_validating_json().unwrap(),
485 JsonValue::Bool(true)
486 );
487 assert_eq!(
488 Value::Bool(false).try_into_validating_json().unwrap(),
489 JsonValue::Bool(false)
490 );
491 }
492
493 #[test]
494 fn validating_json_u8() {
495 let result = Value::U8(42).try_into_validating_json().unwrap();
496 assert_eq!(result, json!(42));
497 }
498
499 #[test]
500 fn validating_json_i8() {
501 let result = Value::I8(-5).try_into_validating_json().unwrap();
502 assert_eq!(result, json!(-5));
503 }
504
505 #[test]
506 fn validating_json_u16() {
507 let result = Value::U16(1000).try_into_validating_json().unwrap();
508 assert_eq!(result, json!(1000));
509 }
510
511 #[test]
512 fn validating_json_i16() {
513 let result = Value::I16(-1000).try_into_validating_json().unwrap();
514 assert_eq!(result, json!(-1000));
515 }
516
517 #[test]
518 fn validating_json_u32() {
519 let result = Value::U32(100_000).try_into_validating_json().unwrap();
520 assert_eq!(result, json!(100_000));
521 }
522
523 #[test]
524 fn validating_json_i32() {
525 let result = Value::I32(-100_000).try_into_validating_json().unwrap();
526 assert_eq!(result, json!(-100_000));
527 }
528
529 #[test]
530 fn validating_json_u64() {
531 let result = Value::U64(u64::MAX).try_into_validating_json().unwrap();
532 assert_eq!(result, json!(u64::MAX));
533 }
534
535 #[test]
536 fn validating_json_i64() {
537 let result = Value::I64(i64::MIN).try_into_validating_json().unwrap();
538 assert_eq!(result, json!(i64::MIN));
539 }
540
541 #[test]
542 fn validating_json_float() {
543 let result = Value::Float(3.14).try_into_validating_json().unwrap();
544 assert_eq!(result, json!(3.14));
545 }
546
547 #[test]
548 fn validating_json_text() {
549 let result = Value::Text("hello".into())
550 .try_into_validating_json()
551 .unwrap();
552 assert_eq!(result, json!("hello"));
553 }
554
555 #[test]
556 fn validating_json_u128_fits_u64() {
557 let val = u64::MAX as u128;
558 let result = Value::U128(val).try_into_validating_json().unwrap();
559 assert_eq!(result, json!(u64::MAX));
560 }
561
562 #[test]
563 fn validating_json_u128_too_large() {
564 let val = u64::MAX as u128 + 1;
565 let err = Value::U128(val).try_into_validating_json().unwrap_err();
566 assert_eq!(err, Error::IntegerSizeError);
567 }
568
569 #[test]
570 fn validating_json_i128_fits_i64_positive() {
571 let val = i64::MAX as i128;
572 let result = Value::I128(val).try_into_validating_json().unwrap();
573 assert_eq!(result, json!(i64::MAX));
574 }
575
576 #[test]
577 fn validating_json_i128_fits_i64_negative() {
578 let val = i64::MIN as i128;
579 let result = Value::I128(val).try_into_validating_json().unwrap();
580 assert_eq!(result, json!(i64::MIN));
581 }
582
583 #[test]
584 fn validating_json_i128_too_large_positive() {
585 let val = i64::MAX as i128 + 1;
586 let err = Value::I128(val).try_into_validating_json().unwrap_err();
587 assert_eq!(err, Error::IntegerSizeError);
588 }
589
590 #[test]
591 fn validating_json_i128_too_small_negative() {
592 let val = i64::MIN as i128 - 1;
593 let err = Value::I128(val).try_into_validating_json().unwrap_err();
594 assert_eq!(err, Error::IntegerSizeError);
595 }
596
597 #[test]
598 fn validating_json_bytes() {
599 let result = Value::Bytes(vec![1, 2, 3])
600 .try_into_validating_json()
601 .unwrap();
602 assert_eq!(result, json!([1, 2, 3]));
603 }
604
605 #[test]
606 fn validating_json_bytes20() {
607 let bytes = [7u8; 20];
608 let result = Value::Bytes20(bytes).try_into_validating_json().unwrap();
609 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
610 assert_eq!(result, JsonValue::Array(arr));
611 }
612
613 #[test]
614 fn validating_json_bytes32() {
615 let bytes = [9u8; 32];
616 let result = Value::Bytes32(bytes).try_into_validating_json().unwrap();
617 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
618 assert_eq!(result, JsonValue::Array(arr));
619 }
620
621 #[test]
622 fn validating_json_bytes36() {
623 let bytes = [11u8; 36];
624 let result = Value::Bytes36(bytes).try_into_validating_json().unwrap();
625 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
626 assert_eq!(result, JsonValue::Array(arr));
627 }
628
629 #[test]
630 fn validating_json_identifier() {
631 let bytes = [0xABu8; 32];
632 let result = Value::Identifier(bytes).try_into_validating_json().unwrap();
633 let arr: Vec<JsonValue> = bytes.iter().map(|b| json!(*b)).collect();
634 assert_eq!(result, JsonValue::Array(arr));
635 }
636
637 #[test]
638 fn validating_json_array_nested() {
639 let val = Value::Array(vec![Value::U64(1), Value::Text("two".into())]);
640 let result = val.try_into_validating_json().unwrap();
641 assert_eq!(result, json!([1, "two"]));
642 }
643
644 #[test]
645 fn validating_json_map() {
646 let map = vec![
647 (Value::Text("a".into()), Value::U64(1)),
648 (Value::Text("b".into()), Value::Bool(true)),
649 ];
650 let val = Value::Map(map);
651 let result = val.try_into_validating_json().unwrap();
652 assert_eq!(result, json!({"a": 1, "b": true}));
653 }
654
655 #[test]
656 fn validating_json_enum_u8_unsupported() {
657 let err = Value::EnumU8(vec![1, 2])
658 .try_into_validating_json()
659 .unwrap_err();
660 assert!(matches!(err, Error::Unsupported(_)));
661 }
662
663 #[test]
664 fn validating_json_enum_string_unsupported() {
665 let err = Value::EnumString(vec!["a".into()])
666 .try_into_validating_json()
667 .unwrap_err();
668 assert!(matches!(err, Error::Unsupported(_)));
669 }
670
671 #[test]
676 fn from_json_null() {
677 let val: Value = JsonValue::Null.into();
678 assert_eq!(val, Value::Null);
679 }
680
681 #[test]
682 fn from_json_bool_true() {
683 let val: Value = json!(true).into();
684 assert_eq!(val, Value::Bool(true));
685 }
686
687 #[test]
688 fn from_json_bool_false() {
689 let val: Value = json!(false).into();
690 assert_eq!(val, Value::Bool(false));
691 }
692
693 #[test]
694 fn from_json_positive_integer() {
695 let val: Value = json!(42).into();
696 assert_eq!(val, Value::U64(42));
697 }
698
699 #[test]
700 fn from_json_negative_integer() {
701 let val: Value = json!(-7).into();
702 assert_eq!(val, Value::I64(-7));
703 }
704
705 #[test]
706 fn from_json_float() {
707 let val: Value = json!(2.5).into();
708 assert_eq!(val, Value::Float(2.5));
709 }
710
711 #[test]
712 fn from_json_string() {
713 let val: Value = json!("hello").into();
714 assert_eq!(val, Value::Text("hello".into()));
715 }
716
717 #[test]
718 fn from_json_object() {
719 let val: Value = json!({"key": "value"}).into();
720 assert!(val.is_map());
721 }
722
723 #[test]
726 fn from_json_array_10_u8_range_becomes_bytes() {
727 let arr: Vec<JsonValue> = (0u64..10).map(|i| json!(i)).collect();
729 let val: Value = JsonValue::Array(arr).into();
730 assert_eq!(val, Value::Bytes(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
731 }
732
733 #[test]
734 fn from_json_array_9_u8_range_stays_array() {
735 let arr: Vec<JsonValue> = (0u64..9).map(|i| json!(i)).collect();
737 let val: Value = JsonValue::Array(arr).into();
738 assert!(matches!(val, Value::Array(_)));
739 }
740
741 #[test]
742 fn from_json_array_mixed_types_stays_array() {
743 let mut arr: Vec<JsonValue> = (0u64..10).map(|i| json!(i)).collect();
745 arr.push(json!("not_a_number"));
746 let val: Value = JsonValue::Array(arr).into();
747 assert!(matches!(val, Value::Array(_)));
748 }
749
750 #[test]
751 fn from_json_array_large_values_stays_array() {
752 let arr: Vec<JsonValue> = (0u64..12).map(|i| json!(i * 100)).collect();
754 let val: Value = JsonValue::Array(arr).into();
755 assert!(matches!(val, Value::Array(_)));
757 }
758
759 #[test]
760 fn from_json_array_all_255_becomes_bytes() {
761 let arr: Vec<JsonValue> = vec![json!(255); 10];
763 let val: Value = JsonValue::Array(arr).into();
764 assert_eq!(val, Value::Bytes(vec![255; 10]));
765 }
766
767 #[test]
768 fn from_json_array_with_negative_stays_array() {
769 let mut arr: Vec<JsonValue> = (0u64..9).map(|i| json!(i)).collect();
771 arr.push(json!(-1));
772 let val: Value = JsonValue::Array(arr).into();
773 assert!(matches!(val, Value::Array(_)));
774 }
775
776 #[test]
781 fn from_json_ref_null() {
782 let jv = JsonValue::Null;
783 let val: Value = (&jv).into();
784 assert_eq!(val, Value::Null);
785 }
786
787 #[test]
788 fn from_json_ref_array_becomes_bytes() {
789 let arr: Vec<JsonValue> = (0u64..15).map(|i| json!(i)).collect();
790 let jv = JsonValue::Array(arr);
791 let val: Value = (&jv).into();
792 assert!(matches!(val, Value::Bytes(_)));
793 }
794
795 #[test]
796 fn from_json_ref_array_short_stays_array() {
797 let arr: Vec<JsonValue> = (0u64..5).map(|i| json!(i)).collect();
798 let jv = JsonValue::Array(arr);
799 let val: Value = (&jv).into();
800 assert!(matches!(val, Value::Array(_)));
801 }
802
803 #[test]
808 fn try_into_json_bytes_become_base64() {
809 let bytes = vec![0xDE, 0xAD, 0xBE, 0xEF];
810 let expected = BASE64_STANDARD.encode(&bytes);
811 let result: JsonValue = Value::Bytes(bytes).try_into().unwrap();
812 assert_eq!(result, JsonValue::String(expected));
813 }
814
815 #[test]
816 fn try_into_json_bytes20_become_base64() {
817 let bytes = [0xAAu8; 20];
818 let expected = BASE64_STANDARD.encode(bytes);
819 let result: JsonValue = Value::Bytes20(bytes).try_into().unwrap();
820 assert_eq!(result, JsonValue::String(expected));
821 }
822
823 #[test]
824 fn try_into_json_bytes32_become_base64() {
825 let bytes = [0xBBu8; 32];
826 let expected = BASE64_STANDARD.encode(bytes);
827 let result: JsonValue = Value::Bytes32(bytes).try_into().unwrap();
828 assert_eq!(result, JsonValue::String(expected));
829 }
830
831 #[test]
832 fn try_into_json_bytes36_become_base64() {
833 let bytes = [0xCCu8; 36];
834 let expected = BASE64_STANDARD.encode(bytes);
835 let result: JsonValue = Value::Bytes36(bytes).try_into().unwrap();
836 assert_eq!(result, JsonValue::String(expected));
837 }
838
839 #[test]
840 fn try_into_json_identifier_becomes_bs58() {
841 let bytes = [0x01u8; 32];
842 let expected = bs58::encode(&bytes).into_string();
843 let result: JsonValue = Value::Identifier(bytes).try_into().unwrap();
844 assert_eq!(result, JsonValue::String(expected));
845 }
846
847 #[test]
848 fn try_into_json_u128_becomes_string() {
849 let result: JsonValue = Value::U128(u128::MAX).try_into().unwrap();
850 assert_eq!(result, JsonValue::String(u128::MAX.to_string()));
851 }
852
853 #[test]
854 fn try_into_json_i128_becomes_string() {
855 let result: JsonValue = Value::I128(i128::MIN).try_into().unwrap();
856 assert_eq!(result, JsonValue::String(i128::MIN.to_string()));
857 }
858
859 #[test]
860 fn try_into_json_null() {
861 let result: JsonValue = Value::Null.try_into().unwrap();
862 assert_eq!(result, JsonValue::Null);
863 }
864
865 #[test]
866 fn try_into_json_bool() {
867 let result: JsonValue = Value::Bool(true).try_into().unwrap();
868 assert_eq!(result, JsonValue::Bool(true));
869 }
870
871 #[test]
872 fn try_into_json_text() {
873 let result: JsonValue = Value::Text("abc".into()).try_into().unwrap();
874 assert_eq!(result, json!("abc"));
875 }
876
877 #[test]
878 fn try_into_json_integer_types() {
879 let r: JsonValue = Value::U8(1).try_into().unwrap();
880 assert_eq!(r, json!(1));
881 let r: JsonValue = Value::I8(-1).try_into().unwrap();
882 assert_eq!(r, json!(-1));
883 let r: JsonValue = Value::U16(500).try_into().unwrap();
884 assert_eq!(r, json!(500));
885 let r: JsonValue = Value::I16(-500).try_into().unwrap();
886 assert_eq!(r, json!(-500));
887 let r: JsonValue = Value::U32(70000).try_into().unwrap();
888 assert_eq!(r, json!(70000));
889 let r: JsonValue = Value::I32(-70000).try_into().unwrap();
890 assert_eq!(r, json!(-70000));
891 let r: JsonValue = Value::U64(123456789).try_into().unwrap();
892 assert_eq!(r, json!(123456789));
893 let r: JsonValue = Value::I64(-123456789).try_into().unwrap();
894 assert_eq!(r, json!(-123456789));
895 }
896
897 #[test]
898 fn try_into_json_array() {
899 let val = Value::Array(vec![Value::U64(1), Value::Bool(false)]);
900 let result: JsonValue = val.try_into().unwrap();
901 assert_eq!(result, json!([1, false]));
902 }
903
904 #[test]
905 fn try_into_json_map() {
906 let map = vec![(Value::Text("x".into()), Value::U64(99))];
907 let val = Value::Map(map);
908 let result: JsonValue = val.try_into().unwrap();
909 assert_eq!(result, json!({"x": 99}));
910 }
911
912 #[test]
913 fn try_into_json_enum_u8_error() {
914 let result: Result<JsonValue, Error> = Value::EnumU8(vec![1]).try_into();
915 assert!(matches!(result, Err(Error::Unsupported(_))));
916 }
917
918 #[test]
919 fn try_into_json_enum_string_error() {
920 let result: Result<JsonValue, Error> = Value::EnumString(vec!["a".into()]).try_into();
921 assert!(matches!(result, Err(Error::Unsupported(_))));
922 }
923
924 #[test]
929 fn round_trip_null() {
930 let original = Value::Null;
931 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
932 let back: Value = json.into();
933 assert_eq!(back, original);
934 }
935
936 #[test]
937 fn round_trip_bool() {
938 let original = Value::Bool(true);
939 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
940 let back: Value = json.into();
941 assert_eq!(back, Value::Bool(true));
942 }
943
944 #[test]
945 fn round_trip_u64() {
946 let original = Value::U64(42);
947 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
948 let back: Value = json.into();
949 assert_eq!(back, Value::U64(42));
951 }
952
953 #[test]
954 fn round_trip_i64() {
955 let original = Value::I64(-42);
956 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
957 let back: Value = json.into();
958 assert_eq!(back, Value::I64(-42));
959 }
960
961 #[test]
962 fn round_trip_text() {
963 let original = Value::Text("hello world".into());
964 let json: JsonValue = original.clone().try_into_validating_json().unwrap();
965 let back: Value = json.into();
966 assert_eq!(back, original);
967 }
968
969 #[test]
974 fn btree_into_json_value() {
975 let mut map = BTreeMap::new();
976 map.insert("x".to_string(), Value::U64(10));
977 map.insert("y".to_string(), Value::Text("test".into()));
978 let json = map.into_json_value().unwrap();
979 assert!(json.is_object());
980 assert_eq!(json["x"], json!(10));
981 assert_eq!(json["y"], json!("test"));
982 }
983
984 #[test]
985 fn btree_into_validating_json_value() {
986 let mut map = BTreeMap::new();
987 map.insert("n".to_string(), Value::U64(5));
988 let json = map.into_validating_json_value().unwrap();
989 assert_eq!(json["n"], json!(5));
990 }
991
992 #[test]
993 fn btree_to_json_value() {
994 let mut map = BTreeMap::new();
995 map.insert("k".to_string(), Value::Bool(true));
996 let json = map.to_json_value().unwrap();
997 assert_eq!(json["k"], json!(true));
998 assert!(map.contains_key("k"));
1000 }
1001
1002 #[test]
1003 fn btree_to_validating_json_value() {
1004 let mut map = BTreeMap::new();
1005 map.insert("v".to_string(), Value::I64(-1));
1006 let json = map.to_validating_json_value().unwrap();
1007 assert_eq!(json["v"], json!(-1));
1008 }
1009
1010 #[test]
1011 fn btree_from_json_value() {
1012 let json = json!({"a": 1, "b": "two"});
1013 let map = BTreeMap::<String, Value>::from_json_value(json).unwrap();
1014 assert_eq!(map.get("a"), Some(&Value::U64(1)));
1015 assert_eq!(map.get("b"), Some(&Value::Text("two".into())));
1016 }
1017
1018 #[test]
1019 fn btree_from_json_value_non_object_error() {
1020 let json = json!([1, 2, 3]);
1021 let result = BTreeMap::<String, Value>::from_json_value(json);
1022 assert!(result.is_err());
1023 }
1024
1025 #[test]
1030 fn from_btree_json_map() {
1031 let mut btree = BTreeMap::new();
1032 btree.insert("key".to_string(), json!(42));
1033 let val: Value = btree.into();
1034 assert!(val.is_map());
1035 }
1036
1037 #[test]
1038 fn from_btree_json_map_ref() {
1039 let mut btree = BTreeMap::new();
1040 btree.insert("key".to_string(), json!(42));
1041 let val: Value = (&btree).into();
1042 assert!(val.is_map());
1043 }
1044
1045 #[test]
1050 fn try_to_validating_json_basic() {
1051 let val = Value::U64(99);
1052 let json = val.try_to_validating_json().unwrap();
1053 assert_eq!(json, json!(99));
1054 }
1055
1056 #[test]
1057 fn try_to_validating_json_u128_too_large() {
1058 let val = Value::U128(u128::MAX);
1059 let err = val.try_to_validating_json().unwrap_err();
1060 assert_eq!(err, Error::IntegerSizeError);
1061 }
1062
1063 #[test]
1064 fn try_to_validating_json_i128_too_large() {
1065 let val = Value::I128(i128::MAX);
1066 let err = val.try_to_validating_json().unwrap_err();
1067 assert_eq!(err, Error::IntegerSizeError);
1068 }
1069
1070 #[test]
1071 fn try_to_validating_json_i128_too_small() {
1072 let val = Value::I128(i128::MIN);
1073 let err = val.try_to_validating_json().unwrap_err();
1074 assert_eq!(err, Error::IntegerSizeError);
1075 }
1076
1077 #[test]
1078 fn try_to_validating_json_enum_u8_error() {
1079 let val = Value::EnumU8(vec![1]);
1080 let err = val.try_to_validating_json().unwrap_err();
1081 assert!(matches!(err, Error::Unsupported(_)));
1082 }
1083
1084 #[test]
1085 fn try_to_validating_json_enum_string_error() {
1086 let val = Value::EnumString(vec!["a".into()]);
1087 let err = val.try_to_validating_json().unwrap_err();
1088 assert!(matches!(err, Error::Unsupported(_)));
1089 }
1090
1091 #[test]
1096 fn try_into_validating_btree_map_json_success() {
1097 let map = vec![(Value::Text("k".into()), Value::U64(7))];
1098 let val = Value::Map(map);
1099 let result = val.try_into_validating_btree_map_json().unwrap();
1100 assert_eq!(result.get("k"), Some(&json!(7)));
1101 }
1102
1103 #[test]
1108 fn convert_from_serde_json_map_basic() {
1109 let pairs = vec![
1110 ("a".to_string(), json!(1)),
1111 ("b".to_string(), json!("hello")),
1112 ];
1113 let result: BTreeMap<String, Value> = Value::convert_from_serde_json_map(pairs);
1114 assert_eq!(result.get("a"), Some(&Value::U64(1)));
1115 assert_eq!(result.get("b"), Some(&Value::Text("hello".into())));
1116 }
1117
1118 #[test]
1119 fn validating_json_float_nan_becomes_zero() {
1120 let result = Value::Float(f64::NAN).try_into_validating_json().unwrap();
1122 assert_eq!(result, json!(0));
1123 }
1124}