lazily-evaluated extractors

This commit is contained in:
2026-02-22 09:23:57 -08:00
parent d994d0943e
commit f466e1c1e3
17 changed files with 512 additions and 386 deletions

View File

@@ -9,8 +9,6 @@ workspace = true
[dependencies]
serde = { workspace = true }
itertools = { workspace = true }
serde_json = { workspace = true }
smartstring = { workspace = true }
[dev-dependencies]

View File

@@ -1,6 +1,4 @@
use itertools::Itertools;
use serde::Deserialize;
use serde_json::Value;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
@@ -12,107 +10,6 @@ pub enum FieldSpecPost {
NotEmpty { notempty: bool },
}
impl FieldSpecPost {
pub fn apply(&self, val: &Value) -> Option<Value> {
Some(match self {
Self::NotEmpty { notempty: false } => val.clone(),
Self::NotEmpty { notempty: true } => match val {
Value::Null => return None,
Value::String(x) if x.is_empty() => return None,
Value::Array(x) if x.is_empty() => return None,
x => x.clone(),
},
Self::SetCase { case: Case::Lower } => match val {
Value::Null => return None,
Value::Bool(_) | Value::Number(_) => val.clone(),
Value::String(x) => Value::String(x.to_lowercase()),
Value::Array(x) => {
Value::Array(x.iter().map(|x| self.apply(x)).collect::<Option<_>>()?)
}
Value::Object(x) => Value::Object(
x.iter()
.map(|x| (x.0.to_lowercase(), self.apply(x.1)))
.map(|x| x.1.map(|y| (x.0, y)))
.collect::<Option<_>>()?,
),
},
Self::SetCase { case: Case::Upper } => match val {
Value::Null => return None,
Value::Bool(_) | Value::Number(_) => val.clone(),
Value::String(x) => Value::String(x.to_uppercase()),
Value::Array(x) => {
Value::Array(x.iter().map(|x| self.apply(x)).collect::<Option<_>>()?)
}
Value::Object(x) => Value::Object(
x.iter()
.map(|x| (x.0.to_uppercase(), self.apply(x.1)))
.map(|x| x.1.map(|y| (x.0, y)))
.collect::<Option<_>>()?,
),
},
Self::TrimSuffix { trim_suffix } => match val {
Value::Null => return None,
Value::Bool(_) | Value::Number(_) => Value::String(val.to_string()),
Value::String(x) => {
Value::String(x.strip_suffix(trim_suffix).unwrap_or(x).to_owned())
}
Value::Array(x) => {
Value::Array(x.iter().map(|x| self.apply(x)).collect::<Option<_>>()?)
}
Value::Object(x) => Value::Object(
x.iter()
.map(|x| {
(
x.0.strip_suffix(trim_suffix).unwrap_or(x.0).to_owned(),
self.apply(x.1),
)
})
.map(|x| x.1.map(|y| (x.0, y)))
.collect::<Option<_>>()?,
),
},
Self::TrimPrefix { trim_prefix } => match val {
Value::Null => return None,
Value::Object(_) => return None,
Value::Bool(_) | Value::Number(_) => Value::String(val.to_string()),
Value::String(x) => {
Value::String(x.strip_prefix(trim_prefix).unwrap_or(x).to_owned())
}
Value::Array(x) => {
Value::Array(x.iter().map(|x| self.apply(x)).collect::<Option<_>>()?)
}
},
Self::Join { join } => match val {
Value::Null => return None,
Value::Object(_) => return None,
Value::Bool(_) | Value::Number(_) => Value::String(val.to_string()),
Value::String(x) => Value::String(x.clone()),
Value::Array(x) => Value::String(
x.iter()
.map(|x| self.apply(x))
.collect::<Option<Vec<_>>>()?
.into_iter()
.join(join),
),
},
})
}
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum Case {