use crate::error::EvaluateError;
use crate::serializer::FieldValueExtractorSerializer;
use crate::value::FieldScalarValue;
use serde::Serialize;
fn validate_path<S: AsRef<str>>(segments: &[S]) -> Result<Vec<String>, EvaluateError> {
if segments.is_empty() {
return Err(EvaluateError::InvalidPath(
"Path cannot be empty".to_string(),
));
}
let segments: Vec<String> = segments.iter().map(|s| s.as_ref().to_string()).collect();
if segments.iter().any(|s| s.is_empty()) {
return Err(EvaluateError::InvalidPath(
"Path segments cannot be empty".to_string(),
));
}
Ok(segments)
}
#[derive(Debug, Clone)]
pub struct FieldExtractor {
field_name: String,
}
impl FieldExtractor {
pub fn new<S: Into<String>>(field_name: S) -> Self {
FieldExtractor {
field_name: field_name.into(),
}
}
pub fn evaluate<T: Serialize>(&self, record: &T) -> Result<FieldScalarValue, EvaluateError> {
let mut serializer = FieldValueExtractorSerializer::new(&self.field_name);
record.serialize(&mut serializer)?;
serializer
.into_result()
.ok_or_else(|| EvaluateError::FieldNotFound {
field_name: self.field_name.clone(),
})
}
}
#[derive(Debug, Clone)]
pub struct NestedFieldExtractor {
path_segments: Vec<String>,
}
impl NestedFieldExtractor {
pub fn new_from_path<S: AsRef<str>>(path_segments: &[S]) -> Result<Self, EvaluateError> {
Ok(NestedFieldExtractor {
path_segments: validate_path(path_segments)?,
})
}
pub fn evaluate<T: Serialize>(&self, value: &T) -> Result<FieldScalarValue, EvaluateError> {
let mut serializer = FieldValueExtractorSerializer::new_nested(self.path_segments.clone());
value.serialize(&mut serializer)?;
serializer
.into_result()
.ok_or_else(|| EvaluateError::NestedFieldNotFound {
path: self.path_segments.clone(),
failed_at_index: None, })
}
}
#[derive(Debug, Clone)]
pub struct CompositeFieldExtractor {
extractors: Vec<NestedFieldExtractor>,
}
impl CompositeFieldExtractor {
pub fn new<S: AsRef<str>>(field_names: &[S]) -> Result<Self, EvaluateError> {
if field_names.is_empty() {
return Err(EvaluateError::InvalidPath(
"Composite extractor requires at least one field".to_string(),
));
}
let extractors = field_names
.iter()
.map(|name| NestedFieldExtractor::new_from_path(&[name.as_ref()]))
.collect::<Result<Vec<_>, _>>()?;
Ok(CompositeFieldExtractor { extractors })
}
pub fn new_from_paths<S: AsRef<str>>(paths: &[&[S]]) -> Result<Self, EvaluateError> {
if paths.is_empty() {
return Err(EvaluateError::InvalidPath(
"Composite extractor requires at least one field".to_string(),
));
}
let extractors = paths
.iter()
.map(|path| NestedFieldExtractor::new_from_path(path))
.collect::<Result<Vec<_>, _>>()?;
Ok(CompositeFieldExtractor { extractors })
}
pub fn evaluate<T: Serialize>(
&self,
record: &T,
) -> Result<Vec<FieldScalarValue>, EvaluateError> {
self.extractors
.iter()
.map(|extractor| extractor.evaluate(record))
.collect()
}
}
#[derive(Debug, Clone)]
pub struct ListFieldExtractor {
field_name: String,
}
impl ListFieldExtractor {
pub fn new<S: Into<String>>(field_name: S) -> Self {
ListFieldExtractor {
field_name: field_name.into(),
}
}
pub fn evaluate<T: Serialize>(
&self,
record: &T,
) -> Result<Vec<FieldScalarValue>, EvaluateError> {
let mut serializer = FieldValueExtractorSerializer::new_list(&self.field_name);
record.serialize(&mut serializer)?;
serializer
.into_list_result()
.ok_or_else(|| EvaluateError::FieldNotFound {
field_name: self.field_name.clone(),
})
}
}
#[derive(Debug, Clone)]
pub struct NestedListFieldExtractor {
path_segments: Vec<String>,
}
impl NestedListFieldExtractor {
pub fn new_from_path<S: AsRef<str>>(path_segments: &[S]) -> Result<Self, EvaluateError> {
Ok(NestedListFieldExtractor {
path_segments: validate_path(path_segments)?,
})
}
pub fn evaluate<T: Serialize>(
&self,
value: &T,
) -> Result<Vec<FieldScalarValue>, EvaluateError> {
let mut serializer =
FieldValueExtractorSerializer::new_nested_list(self.path_segments.clone());
value.serialize(&mut serializer)?;
serializer
.into_list_result()
.ok_or_else(|| EvaluateError::NestedFieldNotFound {
path: self.path_segments.clone(),
failed_at_index: None, })
}
}