compress_json_rs/
memory.rs1use std::collections::HashMap;
2use serde_json::Value;
3use crate::config::CONFIG;
4use crate::debug::throw_unsupported_data;
5use crate::encode::{encode_bool, encode_num, encode_str};
6use crate::number::int_to_s;
7
8pub type Key = String;
10
11pub struct Memory {
13 store: Vec<String>,
14 value_cache: HashMap<String, String>,
15 schema_cache: HashMap<String, String>,
16 key_count: usize,
17}
18
19pub fn mem_to_values(mem: &Memory) -> Vec<String> {
21 mem.store.clone()
22}
23
24pub fn make_memory() -> Memory {
26 Memory {
27 store: Vec::new(),
28 value_cache: HashMap::new(),
29 schema_cache: HashMap::new(),
30 key_count: 0,
31 }
32}
33
34fn get_value_key(mem: &mut Memory, value: &str) -> String {
36 if let Some(key) = mem.value_cache.get(value) {
37 return key.clone();
38 }
39 let id = mem.key_count;
40 let key = int_to_s(id);
41 mem.key_count += 1;
42 mem.store.push(value.to_string());
43 mem.value_cache.insert(value.to_string(), key.clone());
44 key
45}
46
47fn get_schema(mem: &mut Memory, keys: &[String]) -> String {
49 let mut schema_keys = keys.to_vec();
50 if CONFIG.sort_key {
51 schema_keys.sort();
52 }
53 let schema = schema_keys.join(",");
54 if let Some(key) = mem.schema_cache.get(&schema) {
55 return key.clone();
56 }
57 let arr = Value::Array(
59 schema_keys
60 .iter()
61 .map(|k| Value::String(k.clone()))
62 .collect(),
63 );
64 let key_id = add_value(mem, &arr);
65 mem.schema_cache.insert(schema, key_id.clone());
66 key_id
67}
68
69pub fn add_value(mem: &mut Memory, o: &Value) -> Key {
71 match o {
72 Value::Null => "".to_string(),
73 Value::Bool(b) => get_value_key(mem, &encode_bool(*b)),
74 Value::Number(n) => {
75 let f = n.as_f64().unwrap_or_else(|| {
77 n.as_i64()
79 .map(|i| i as f64)
80 .or_else(|| n.as_u64().map(|u| u as f64))
81 .unwrap_or(0.0)
82 });
83 if f.is_nan() {
84 if CONFIG.error_on_nan {
85 throw_unsupported_data("[number NaN]");
86 }
87 return "".to_string();
88 }
89 if f.is_infinite() {
90 if CONFIG.error_on_infinite {
91 throw_unsupported_data("[number Infinity]");
92 }
93 return "".to_string();
94 }
95 get_value_key(mem, &encode_num(f))
96 }
97 Value::String(s) => get_value_key(mem, &encode_str(s)),
98 Value::Array(arr) => {
99 let mut acc = String::from("a");
100 for v in arr.iter() {
101 let key = if v.is_null() {
102 "_".to_string()
103 } else {
104 add_value(mem, v)
105 };
106 acc.push('|');
107 acc.push_str(&key);
108 }
109 if acc == "a" {
110 acc = "a|".to_string();
111 }
112 get_value_key(mem, &acc)
113 }
114 Value::Object(map) => {
115 let keys: Vec<String> = map.keys().cloned().collect();
116 if keys.is_empty() {
117 return get_value_key(mem, "o|");
118 }
119 let key_id = get_schema(mem, &keys);
120 let mut acc = String::from("o|");
121 acc.push_str(&key_id);
122 for key in keys.iter() {
123 let v = &map[key];
124 let val_key = add_value(mem, v);
125 acc.push('|');
126 acc.push_str(&val_key);
127 }
128 get_value_key(mem, &acc)
129 }
130 _ => panic!("unsupported data type"),
131 }
132}