use crate::entities::re::ParseJsonError;
use serde_json::{Map, Value};
pub(crate) trait FieldGetter {
type T;
fn with_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&Self::T>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError>;
fn with_primary_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(&Self::T) -> Result<R, ParseJsonError>,
) -> Result<Option<R>, ParseJsonError> {
Self::with_field(dict, key, &|f| match f {
Some(val) => Ok(Some(predicate(val)?)),
_ => Ok(None),
})
}
fn with_param_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(&Self::T) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
Self::with_field(dict, key, &|f| match f {
Some(val) => predicate(val),
_ => ParseJsonError::not_found(key),
})
}
fn with_param_nullable_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&Self::T>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
if let Some(Value::Null) = dict.get(&key.to_string()) {
return predicate(None);
}
Self::with_field(dict, key, &|f| match f {
Some(val) => predicate(Some(val)),
_ => ParseJsonError::not_found(key),
})
}
}
pub struct UsizeFieldGetter {}
pub struct BoolFieldGetter {}
pub struct StrFieldGetter {}
pub struct VecFieldGetter {}
pub struct ValueFieldGetter {}
impl FieldGetter for UsizeFieldGetter {
type T = usize;
fn with_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&usize>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
match dict.get(&key.to_string()) {
Some(Value::Number(num)) => {
let int = match num.as_u64() {
Some(val) => val as usize,
_ => return ParseJsonError::invalid_value(key, "int"),
};
predicate(Some(&int))
}
Some(_) => ParseJsonError::invalid_value(key, "int"),
None => predicate(None),
}
}
}
impl FieldGetter for BoolFieldGetter {
type T = bool;
fn with_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&Self::T>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
match dict.get(&key.to_string()) {
Some(Value::Bool(ref val)) => predicate(Some(val)),
Some(_) => ParseJsonError::invalid_value(key, "bool"),
None => predicate(None),
}
}
}
impl FieldGetter for VecFieldGetter {
type T = Vec<Value>;
fn with_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&Self::T>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
match dict.get(&key.to_string()) {
Some(Value::Array(ref val)) => predicate(Some(val)),
Some(_) => ParseJsonError::invalid_value(key, "list"),
None => predicate(None),
}
}
}
impl FieldGetter for StrFieldGetter {
type T = String;
fn with_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&Self::T>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
match dict.get(&key.to_string()) {
Some(Value::String(ref val)) => predicate(Some(val)),
Some(_) => ParseJsonError::invalid_value(key, "str"),
None => predicate(None),
}
}
}
impl FieldGetter for ValueFieldGetter {
type T = Value;
fn with_field<R>(
dict: &Map<String, Value>,
key: &str,
predicate: &dyn Fn(Option<&Self::T>) -> Result<R, ParseJsonError>,
) -> Result<R, ParseJsonError> {
predicate(dict.get(&key.to_string()))
}
}