Skip to main content

promkit_widgets/jsonstream/
jsonz.rs

1use rayon::prelude::*;
2
3#[derive(Clone, Debug, PartialEq)]
4pub enum ContainerType {
5    Object,
6    Array,
7}
8
9impl ContainerType {
10    pub fn open_str(&self) -> &'static str {
11        match self {
12            ContainerType::Object => "{",
13            ContainerType::Array => "[",
14        }
15    }
16
17    pub fn close_str(&self) -> &'static str {
18        match self {
19            ContainerType::Object => "}",
20            ContainerType::Array => "]",
21        }
22    }
23
24    pub fn empty_str(&self) -> &'static str {
25        match self {
26            ContainerType::Object => "{}",
27            ContainerType::Array => "[]",
28        }
29    }
30
31    pub fn collapsed_preview(&self) -> &'static str {
32        match self {
33            ContainerType::Object => "{…}",
34            ContainerType::Array => "[…]",
35        }
36    }
37}
38
39#[derive(Clone, Debug, PartialEq)]
40pub enum Value {
41    Null,
42    Boolean(bool),
43    Number(serde_json::Number),
44    String(String),
45    Empty {
46        typ: ContainerType,
47    },
48    Open {
49        typ: ContainerType,
50        collapsed: bool,
51        close_index: usize,
52    },
53    Close {
54        typ: ContainerType,
55        collapsed: bool,
56        open_index: usize,
57    },
58}
59
60#[derive(Clone, Debug, PartialEq)]
61pub struct Row {
62    pub depth: usize,
63    pub k: Option<String>,
64    pub v: Value,
65}
66
67pub trait RowOperation {
68    fn up(&self, current: usize) -> usize;
69    fn head(&self) -> usize;
70    fn down(&self, current: usize) -> usize;
71    fn tail(&self) -> usize;
72    fn toggle(&mut self, current: usize) -> usize;
73    fn set_rows_visibility(&mut self, collapsed: bool);
74    fn extract(&self, current: usize, n: usize) -> Vec<Row>;
75}
76
77impl RowOperation for Vec<Row> {
78    fn up(&self, current: usize) -> usize {
79        if current == 0 {
80            return 0;
81        }
82
83        let prev = current - 1;
84        match &self[prev].v {
85            Value::Close {
86                collapsed,
87                open_index,
88                ..
89            } if *collapsed => *open_index,
90            _ => prev,
91        }
92    }
93
94    fn head(&self) -> usize {
95        0
96    }
97
98    fn down(&self, current: usize) -> usize {
99        if current >= self.len() - 1 {
100            return current;
101        }
102
103        let next = current + 1;
104        match &self[current].v {
105            Value::Open {
106                collapsed,
107                close_index,
108                ..
109            } if *collapsed => {
110                let next_pos = close_index + 1;
111                if next_pos >= self.len() {
112                    current
113                } else {
114                    next_pos
115                }
116            }
117            _ => next,
118        }
119    }
120
121    fn tail(&self) -> usize {
122        if self.is_empty() {
123            return 0;
124        }
125
126        let mut last = self.len() - 1;
127        match &self[last].v {
128            Value::Close {
129                collapsed,
130                open_index,
131                ..
132            } if *collapsed => {
133                last = *open_index;
134                last
135            }
136            _ => last,
137        }
138    }
139
140    fn toggle(&mut self, current: usize) -> usize {
141        match &self[current].v {
142            Value::Open {
143                typ,
144                collapsed,
145                close_index,
146            } => {
147                let new_collapsed = !collapsed;
148                let close_idx = *close_index;
149                let typ_clone = typ.clone();
150
151                self[current].v = Value::Open {
152                    typ: typ_clone.clone(),
153                    collapsed: new_collapsed,
154                    close_index: close_idx,
155                };
156
157                self[close_idx].v = Value::Close {
158                    typ: typ_clone,
159                    collapsed: new_collapsed,
160                    open_index: current,
161                };
162
163                current
164            }
165            Value::Close {
166                typ,
167                collapsed,
168                open_index,
169            } => {
170                let new_collapsed = !collapsed;
171                let open_idx = *open_index;
172                let typ_clone = typ.clone();
173
174                self[current].v = Value::Close {
175                    typ: typ_clone.clone(),
176                    collapsed: new_collapsed,
177                    open_index: open_idx,
178                };
179
180                self[open_idx].v = Value::Open {
181                    typ: typ_clone,
182                    collapsed: new_collapsed,
183                    close_index: current,
184                };
185
186                if new_collapsed { open_idx } else { current }
187            }
188            _ => current,
189        }
190    }
191
192    fn set_rows_visibility(&mut self, collapsed: bool) {
193        self.par_iter_mut().for_each(|row| {
194            if let Value::Open {
195                typ, close_index, ..
196            } = &row.v
197            {
198                row.v = Value::Open {
199                    typ: typ.clone(),
200                    collapsed,
201                    close_index: *close_index,
202                };
203            } else if let Value::Close {
204                typ, open_index, ..
205            } = &row.v
206            {
207                row.v = Value::Close {
208                    typ: typ.clone(),
209                    collapsed,
210                    open_index: *open_index,
211                };
212            }
213        });
214    }
215
216    fn extract(&self, current: usize, n: usize) -> Vec<Row> {
217        let mut result = Vec::new();
218        let mut i = current;
219        let mut remaining = n;
220
221        while i < self.len() && remaining > 0 {
222            result.push(self[i].clone());
223            remaining -= 1;
224
225            match &self[i].v {
226                Value::Open {
227                    collapsed: true,
228                    close_index,
229                    ..
230                } => {
231                    i = *close_index + 1;
232                }
233                _ => {
234                    i += 1;
235                }
236            }
237        }
238
239        result
240    }
241}
242
243fn process_value(
244    value: &serde_json::Value,
245    rows: &mut Vec<Row>,
246    depth: usize,
247    key: Option<String>,
248) -> usize {
249    match value {
250        serde_json::Value::Null => {
251            rows.push(Row {
252                depth,
253                k: key,
254                v: Value::Null,
255            });
256            rows.len() - 1
257        }
258        serde_json::Value::Bool(b) => {
259            rows.push(Row {
260                depth,
261                k: key,
262                v: Value::Boolean(*b),
263            });
264            rows.len() - 1
265        }
266        serde_json::Value::Number(n) => {
267            rows.push(Row {
268                depth,
269                k: key,
270                v: Value::Number(n.clone()),
271            });
272            rows.len() - 1
273        }
274        serde_json::Value::String(s) => {
275            rows.push(Row {
276                depth,
277                k: key,
278                v: Value::String(s.clone()),
279            });
280            rows.len() - 1
281        }
282        serde_json::Value::Array(arr) => {
283            if arr.is_empty() {
284                rows.push(Row {
285                    depth,
286                    k: key,
287                    v: Value::Empty {
288                        typ: ContainerType::Array,
289                    },
290                });
291                return rows.len() - 1;
292            }
293
294            let open_index = rows.len();
295
296            rows.push(Row {
297                depth,
298                k: key,
299                v: Value::Open {
300                    typ: ContainerType::Array,
301                    collapsed: false,
302                    close_index: 0,
303                },
304            });
305
306            for value in arr {
307                process_value(value, rows, depth + 1, None);
308            }
309
310            let close_index = rows.len();
311            rows.push(Row {
312                depth,
313                k: None,
314                v: Value::Close {
315                    typ: ContainerType::Array,
316                    collapsed: false,
317                    open_index,
318                },
319            });
320
321            rows[open_index].v = Value::Open {
322                typ: ContainerType::Array,
323                collapsed: false,
324                close_index,
325            };
326
327            open_index
328        }
329        serde_json::Value::Object(obj) => {
330            if obj.is_empty() {
331                rows.push(Row {
332                    depth,
333                    k: key,
334                    v: Value::Empty {
335                        typ: ContainerType::Object,
336                    },
337                });
338                return rows.len() - 1;
339            }
340
341            let open_index = rows.len();
342
343            rows.push(Row {
344                depth,
345                k: key,
346                v: Value::Open {
347                    typ: ContainerType::Object,
348                    collapsed: false,
349                    close_index: 0,
350                },
351            });
352
353            for (key, value) in obj {
354                process_value(value, rows, depth + 1, Some(key.clone()));
355            }
356
357            let close_index = rows.len();
358            rows.push(Row {
359                depth,
360                k: None,
361                v: Value::Close {
362                    typ: ContainerType::Object,
363                    collapsed: false,
364                    open_index,
365                },
366            });
367
368            rows[open_index].v = Value::Open {
369                typ: ContainerType::Object,
370                collapsed: false,
371                close_index,
372            };
373
374            open_index
375        }
376    }
377}
378
379pub fn create_rows<'a, T: IntoIterator<Item = &'a serde_json::Value>>(iter: T) -> Vec<Row> {
380    let mut rows = Vec::new();
381    for value in iter {
382        process_value(value, &mut rows, 0, None);
383    }
384    rows
385}
386
387#[derive(Debug)]
388pub struct PathIterator<'a> {
389    stack: Vec<(String, &'a serde_json::Value)>,
390}
391
392impl PathIterator<'_> {
393    fn escape_json_path_key(key: &str) -> String {
394        if key.contains('.') || key.contains('-') || key.contains('@') {
395            format!("\"{}\"", key)
396        } else {
397            key.to_string()
398        }
399    }
400}
401
402impl Iterator for PathIterator<'_> {
403    type Item = String;
404
405    fn next(&mut self) -> Option<Self::Item> {
406        if let Some((current_path, value)) = self.stack.pop() {
407            match value {
408                serde_json::Value::Object(obj) => {
409                    for (key, val) in obj.iter() {
410                        let escaped = Self::escape_json_path_key(key);
411                        let new_path = if current_path == "." {
412                            format!(".{}", escaped)
413                        } else {
414                            format!("{}.{}", current_path, escaped)
415                        };
416                        self.stack.push((new_path, val));
417                    }
418                }
419                serde_json::Value::Array(arr) => {
420                    for (i, val) in arr.iter().enumerate() {
421                        let new_path = format!("{}[{}]", current_path, i);
422                        self.stack.push((new_path, val));
423                    }
424                }
425                _ => {}
426            }
427
428            Some(current_path)
429        } else {
430            None
431        }
432    }
433}
434
435pub fn get_all_paths<'a, T: IntoIterator<Item = &'a serde_json::Value>>(
436    iter: T,
437) -> impl Iterator<Item = String> + 'a {
438    let mut stack = Vec::new();
439    for value in iter {
440        stack.push((".".to_string(), value));
441    }
442    PathIterator { stack }
443}