use crate::value::Value;
use super::Column;
pub(super) fn build_column(items: &[Value], field: &str, seed: &Value) -> Option<Column> {
match seed {
Value::Int(_) => build_col(items, field, value_as_int).map(Column::Int),
Value::Float(f) if !f.is_nan() => {
build_col(items, field, value_as_float).map(Column::Float)
}
Value::Str(_) => build_col(items, field, value_as_str).map(Column::Str),
Value::Bool(_) => build_col(items, field, value_as_bool).map(Column::Bool),
_ => None,
}
}
fn build_col<T>(
items: &[Value],
field: &str,
extract: impl Fn(&Value) -> Option<T>,
) -> Option<Vec<T>> {
let mut col = Vec::with_capacity(items.len());
for item in items {
col.push(extract(field_value(item, field)?)?);
}
Some(col)
}
fn field_value<'a>(item: &'a Value, field: &str) -> Option<&'a Value> {
match item {
Value::Map(map) => map.get(field),
_ => None,
}
}
pub(super) fn value_as_int(value: &Value) -> Option<i64> {
match value {
Value::Int(n) => Some(*n),
_ => None,
}
}
fn value_as_float(value: &Value) -> Option<f64> {
match value {
Value::Float(f) if !f.is_nan() => Some(*f),
_ => None,
}
}
pub(super) fn value_as_str(value: &Value) -> Option<String> {
match value {
Value::Str(s) => Some(s.clone()),
_ => None,
}
}
pub(super) fn value_as_bool(value: &Value) -> Option<bool> {
match value {
Value::Bool(b) => Some(*b),
_ => None,
}
}