Improve arg parsing
This commit is contained in:
@@ -4,20 +4,6 @@ use std::sync::Arc;
|
||||
|
||||
use crate::{extract::traits::ObjectExtractor, value::PileValue};
|
||||
|
||||
fn parse_name(s: &str) -> (&str, Option<&str>) {
|
||||
match s.find('(') {
|
||||
None => (s, None),
|
||||
Some(i) => {
|
||||
let name = &s[..i];
|
||||
let rest = &s[i + 1..];
|
||||
match rest.strip_suffix(')') {
|
||||
Some(args) => (name, Some(args)),
|
||||
None => (name, None),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StringExtractor {
|
||||
item: Arc<SmartString<LazyCompact>>,
|
||||
}
|
||||
@@ -30,9 +16,12 @@ impl StringExtractor {
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ObjectExtractor for StringExtractor {
|
||||
async fn field(&self, name: &Label) -> Result<Option<PileValue>, std::io::Error> {
|
||||
let (name, args) = parse_name(name.as_str());
|
||||
Ok(match (name, args) {
|
||||
async fn field(
|
||||
&self,
|
||||
name: &Label,
|
||||
args: Option<&str>,
|
||||
) -> Result<Option<PileValue>, std::io::Error> {
|
||||
Ok(match (name.as_str(), args) {
|
||||
("trim", None) => Some(PileValue::String(Arc::new(
|
||||
self.item.as_str().trim().into(),
|
||||
))),
|
||||
@@ -98,8 +87,8 @@ mod tests {
|
||||
}
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
async fn field(ext: &StringExtractor, name: &str) -> Option<PileValue> {
|
||||
ext.field(&Label::new(name).unwrap()).await.unwrap()
|
||||
async fn field(ext: &StringExtractor, name: &str, args: Option<&str>) -> Option<PileValue> {
|
||||
ext.field(&Label::new(name).unwrap(), args).await.unwrap()
|
||||
}
|
||||
|
||||
fn string(v: Option<PileValue>) -> Option<String> {
|
||||
@@ -125,20 +114,20 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn trim() {
|
||||
assert_eq!(
|
||||
string(field(&extractor(" hi "), "trim").await),
|
||||
string(field(&extractor(" hi "), "trim", None).await),
|
||||
Some("hi".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn trim_no_args() {
|
||||
assert!(field(&extractor("x"), "trim(foo)").await.is_none());
|
||||
assert!(field(&extractor("x"), "trim", Some("foo")).await.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn nonempty_with_content() {
|
||||
assert!(matches!(
|
||||
field(&extractor("hello"), "nonempty").await,
|
||||
field(&extractor("hello"), "nonempty", None).await,
|
||||
Some(PileValue::String(_))
|
||||
));
|
||||
}
|
||||
@@ -146,7 +135,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn nonempty_empty_string() {
|
||||
assert!(matches!(
|
||||
field(&extractor(""), "nonempty").await,
|
||||
field(&extractor(""), "nonempty", None).await,
|
||||
Some(PileValue::Null)
|
||||
));
|
||||
}
|
||||
@@ -154,7 +143,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn trimprefix_present() {
|
||||
assert_eq!(
|
||||
string(field(&extractor("foobar"), "trimprefix(foo)").await),
|
||||
string(field(&extractor("foobar"), "trimprefix", Some("foo")).await),
|
||||
Some("bar".into())
|
||||
);
|
||||
}
|
||||
@@ -162,20 +151,24 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn trimprefix_absent() {
|
||||
assert_eq!(
|
||||
string(field(&extractor("foobar"), "trimprefix(baz)").await),
|
||||
string(field(&extractor("foobar"), "trimprefix", Some("baz")).await),
|
||||
Some("foobar".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn trimprefix_no_args() {
|
||||
assert!(field(&extractor("foobar"), "trimprefix").await.is_none());
|
||||
assert!(
|
||||
field(&extractor("foobar"), "trimprefix", None)
|
||||
.await
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn trimsuffix_present() {
|
||||
assert_eq!(
|
||||
string(field(&extractor("foobar"), "trimsuffix(bar)").await),
|
||||
string(field(&extractor("foobar"), "trimsuffix", Some("bar")).await),
|
||||
Some("foo".into())
|
||||
);
|
||||
}
|
||||
@@ -183,7 +176,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn trimsuffix_absent() {
|
||||
assert_eq!(
|
||||
string(field(&extractor("foobar"), "trimsuffix(baz)").await),
|
||||
string(field(&extractor("foobar"), "trimsuffix", Some("baz")).await),
|
||||
Some("foobar".into())
|
||||
);
|
||||
}
|
||||
@@ -191,7 +184,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn split_basic() {
|
||||
assert_eq!(
|
||||
array(field(&extractor("a,b,c"), "split(,)").await),
|
||||
array(field(&extractor("a,b,c"), "split", Some(",")).await),
|
||||
vec!["a", "b", "c"]
|
||||
);
|
||||
}
|
||||
@@ -199,23 +192,18 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn split_no_match() {
|
||||
assert_eq!(
|
||||
array(field(&extractor("abc"), "split(,)").await),
|
||||
array(field(&extractor("abc"), "split", Some(",")).await),
|
||||
vec!["abc"]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn split_no_args() {
|
||||
assert!(field(&extractor("abc"), "split").await.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn split_unclosed_paren() {
|
||||
assert!(field(&extractor("abc"), "split(,").await.is_none());
|
||||
assert!(field(&extractor("abc"), "split", None).await.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unknown_field() {
|
||||
assert!(field(&extractor("abc"), "bogus").await.is_none());
|
||||
assert!(field(&extractor("abc"), "bogus", None).await.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user