1use serde_json::{Map, Value};
4
5use crate::Error;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum KeyAction {
10 Skip,
12 Walk,
14 WalkAll,
17 JsonString,
20}
21
22pub trait KeyPolicy: Sync {
24 fn action(&self, parent: &Map<String, Value>, key: &str) -> KeyAction;
26}
27
28pub struct WalkAll;
30
31impl KeyPolicy for WalkAll {
32 fn action(&self, _: &Map<String, Value>, _: &str) -> KeyAction {
33 KeyAction::Walk
34 }
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub(crate) enum StrKind {
40 Plain,
41 Json,
42}
43
44pub(crate) type Visitor<'a> = dyn FnMut(&mut String, StrKind) -> Result<(), Error> + 'a;
45
46pub(crate) fn walk(value: &mut Value, policy: &dyn KeyPolicy, f: &mut Visitor<'_>) -> Result<(), Error> {
47 match value {
48 Value::String(s) => f(s, StrKind::Plain),
49 Value::Array(items) => items.iter_mut().try_for_each(|v| walk(v, policy, f)),
50 Value::Object(map) => {
51 let actions: Vec<(String, KeyAction)> = map.keys().map(|k| (k.clone(), policy.action(map, k))).collect();
52 for (key, action) in actions {
53 let child = map.get_mut(&key).expect("key exists");
54 match action {
55 KeyAction::Skip => {}
56 KeyAction::Walk => walk(child, policy, f)?,
57 KeyAction::WalkAll => walk(child, &WalkAll, f)?,
58 KeyAction::JsonString => match child {
59 Value::String(s) => f(s, StrKind::Json)?,
60 other => walk(other, &WalkAll, f)?,
61 },
62 }
63 }
64 Ok(())
65 }
66 Value::Null | Value::Bool(_) | Value::Number(_) => Ok(()),
67 }
68}