1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
//! Memory management for compression state.
//!
//! This module provides the [`Memory`] struct and related functions for managing
//! the compression state. It handles value deduplication through caching and
//! schema sharing for objects with identical keys.
//!
//! # Architecture
//!
//! The memory system consists of:
//! - **Store**: A vector of encoded string values
//! - **Value Cache**: HashMap for deduplicating identical values
//! - **Schema Cache**: HashMap for deduplicating object schemas (key lists)
//!
//! # Deduplication
//!
//! When a value is added:
//! 1. It's first checked against the value cache
//! 2. If found, the existing key is returned (no new storage)
//! 3. If not found, a new key is generated and the value is stored
//!
//! This ensures that identical values (like repeated strings or numbers)
//! are only stored once.
//!
//! # Example
//!
//! ```rust
//! use compress_json_rs::{make_memory, add_value, mem_to_values};
//! use serde_json::json;
//!
//! let mut mem = make_memory();
//!
//! // Adding the same value twice returns the same key
//! let key1 = add_value(&mut mem, &json!("repeated"));
//! let key2 = add_value(&mut mem, &json!("repeated"));
//! assert_eq!(key1, key2);
//!
//! // The value is only stored once
//! let values = mem_to_values(&mem);
//! assert_eq!(values.len(), 1);
//! ```
use crateCONFIG;
use cratethrow_unsupported_data;
use crate;
use crateint_to_s;
use Value;
use HashMap;
/// Key type for compressed references.
///
/// Keys are base-62 encoded strings that reference positions in the values array.
/// The base-62 encoding uses characters `0-9`, `A-Z`, and `a-z`.
///
/// # Examples
///
/// - `"0"` - First value (index 0)
/// - `"A"` - Eleventh value (index 10)
/// - `"10"` - Sixty-third value (index 62)
pub type Key = String;
/// In-memory structure holding store and caches for compression.
///
/// This struct maintains the state needed during compression. It uses
/// internal caching to deduplicate values and object schemas.
///
/// # Fields (Internal)
///
/// | Field | Type | Description |
/// |-------|------|-------------|
/// | `store` | `Vec<String>` | Encoded string values |
/// | `value_cache` | `HashMap` | Maps values to keys |
/// | `schema_cache` | `HashMap` | Maps schemas to keys |
/// | `key_count` | `usize` | Key counter |
///
/// # Usage
///
/// Create with [`make_memory`], add values with [`add_value`], and extract
/// the final values array with [`mem_to_values`].
///
/// # Example
///
/// ```rust
/// use compress_json_rs::{Memory, make_memory, add_value, mem_to_values};
/// use serde_json::json;
///
/// // Create memory store
/// let mut mem: Memory = make_memory();
///
/// // Add values (duplicates are deduplicated)
/// let k1 = add_value(&mut mem, &json!("hello"));
/// let k2 = add_value(&mut mem, &json!("hello"));
/// assert_eq!(k1, k2);
///
/// // Extract values
/// let values = mem_to_values(&mem);
/// assert_eq!(values.len(), 1);
/// ```
/// Convert internal store to values array.
///
/// Extracts the values vector from a `Memory` instance. This is typically
/// called after all values have been added to get the final compressed output.
///
/// # Arguments
///
/// * `mem` - Reference to the Memory instance
///
/// # Returns
///
/// A clone of the internal values vector
///
/// # Example
///
/// ```rust
/// use compress_json_rs::{make_memory, add_value, mem_to_values};
/// use serde_json::json;
///
/// let mut mem = make_memory();
/// add_value(&mut mem, &json!({"key": "value"}));
/// let values = mem_to_values(&mem);
/// assert!(!values.is_empty());
/// ```
/// Create a new in-memory Memory instance.
///
/// Initializes an empty `Memory` struct ready to accept values.
///
/// # Returns
///
/// A new, empty Memory instance
///
/// # Example
///
/// ```rust
/// use compress_json_rs::make_memory;
///
/// let mem = make_memory();
/// // Ready to use with add_value()
/// ```
/// Get or insert a value in the store, returning its key.
///
/// This is the core deduplication function. It checks if the encoded value
/// already exists in the cache, returning the existing key if so. Otherwise,
/// it generates a new key, stores the value, and caches the mapping.
/// Get or insert a schema (object keys), returning its key.
///
/// Schemas are stored as arrays of key strings. Objects with identical
/// keys share the same schema, reducing storage for arrays of similar objects.
/// Recursively add a JSON value to memory, returning its key.
///
/// This function handles all JSON value types and recursively processes
/// nested arrays and objects. Values are deduplicated through the internal
/// cache.
///
/// # Arguments
///
/// * `mem` - Mutable reference to the Memory instance
/// * `o` - Reference to the JSON value to add
///
/// # Returns
///
/// A base-62 encoded key string referencing the stored value
///
/// # Value Encoding
///
/// | Type | Encoding | Example |
/// |------|----------|---------|
/// | Null | Empty string | `""` |
/// | Bool | `b\|T` or `b\|F` | `"b\|T"` |
/// | Number | `n\|<value>` | `"n\|42.5"` |
/// | String | Plain or `s\|<escaped>` | `"hello"` or `"s\|n\|123"` |
/// | Array | `a\|<refs>` | `"a\|0\|1\|2"` |
/// | Object | `o\|<schema>\|<refs>` | `"o\|0\|1\|2"` |
///
/// # Example
///
/// ```rust
/// use compress_json_rs::{make_memory, add_value, mem_to_values, decode};
/// use serde_json::json;
///
/// let mut mem = make_memory();
///
/// // Add a complex value
/// let key = add_value(&mut mem, &json!({
/// "name": "Alice",
/// "scores": [95, 87, 92]
/// }));
///
/// // The key can be used to decode back
/// let values = mem_to_values(&mem);
/// let decoded = decode(&values, &key);
/// assert_eq!(decoded["name"], "Alice");
/// ```
///
/// # Special Cases (v3.4.0+)
///
/// Special value handling depends on configuration:
///
/// | Value | `preserve_*` = true | `preserve_*` = false, `error_*` = true | Both false |
/// |-------|---------------------|----------------------------------------|------------|
/// | NaN | Encoded as `N\|0` | Panic | Returns `""` (null) |
/// | Infinity | Encoded as `N\|+` | Panic | Returns `""` (null) |
/// | -Infinity | Encoded as `N\|-` | Panic | Returns `""` (null) |
///
/// - **Null in arrays**: Encoded as `_` to distinguish from empty references