1use aws_smithy_types::Document;
2use serde_json::Value;
3use std::collections::{BTreeMap, HashMap};
4
5fn create_sorted_hashmap(sorted: BTreeMap<String, Document>) -> HashMap<String, Document> {
19 const MAX_RETRIES: usize = 100;
20
21 for _ in 0..MAX_RETRIES {
22 let mut map = HashMap::new();
23 for (k, v) in &sorted {
24 map.insert(k.clone(), v.clone());
25 }
26
27 let keys: Vec<_> = map.keys().collect();
28 let sorted_keys: Vec<_> = sorted.keys().collect();
29
30 if keys == sorted_keys {
31 return map;
32 }
33 }
34
35 let mut map = HashMap::new();
36 for (k, v) in sorted {
37 map.insert(k, v);
38 }
39 map
40}
41
42pub fn to_doc(value: Value) -> Document {
44 match value {
45 Value::Null => Document::Null,
46 Value::Bool(b) => Document::Bool(b),
47 Value::Number(n) => {
48 if let Some(u) = n.as_u64() {
49 Document::Number(aws_smithy_types::Number::PosInt(u))
50 } else if let Some(i) = n.as_i64() {
51 Document::Number(aws_smithy_types::Number::NegInt(i))
52 } else if let Some(f) = n.as_f64() {
53 Document::Number(aws_smithy_types::Number::Float(f))
54 } else {
55 Document::Null
56 }
57 }
58 Value::String(s) => Document::String(s),
59 Value::Array(arr) => Document::Array(arr.into_iter().map(to_doc).collect()),
60 Value::Object(obj) => {
61 let sorted: BTreeMap<String, Document> =
65 obj.into_iter().map(|(k, v)| (k, to_doc(v))).collect();
66 Document::Object(create_sorted_hashmap(sorted))
67 }
68 }
69}
70
71pub fn from_doc(doc: Document) -> Value {
73 match doc {
74 Document::Null => Value::Null,
75 Document::Bool(b) => Value::Bool(b),
76 Document::Number(n) => match n {
77 aws_smithy_types::Number::PosInt(u) => Value::Number(u.into()),
78 aws_smithy_types::Number::NegInt(i) => Value::Number(i.into()),
79 aws_smithy_types::Number::Float(f) => serde_json::Number::from_f64(f)
80 .map(Value::Number)
81 .unwrap_or(Value::Null),
82 },
83 Document::String(s) => Value::String(s),
84 Document::Array(arr) => Value::Array(arr.into_iter().map(from_doc).collect()),
85 Document::Object(obj) => {
86 Value::Object(obj.into_iter().map(|(k, v)| (k, from_doc(v))).collect())
87 }
88 }
89}