use std::collections::HashMap;
#[cfg(feature = "python")]
mod python;
mod basic_operation;
mod deserializer;
mod extract;
mod from;
mod operators;
mod utils;
pub use smartstring::alias::String;
#[derive(Debug, Clone, Default)]
pub enum DataValue {
String(String),
Bytes(Vec<u8>),
U8(u8),
Bool(bool),
I32(i32),
U32(u32),
I64(i64),
U64(u64),
I128(i128),
U128(u128),
F32(f32),
F64(f64),
Map(HashMap<String, DataValue>),
Vec(Vec<DataValue>),
EnumNumber(i32),
#[default]
Null,
}
impl std::fmt::Display for DataValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use DataValue::*;
match self {
Bool(i) => write!(f, "{}", i),
U32(i) => write!(f, "{}", i),
I32(i) => write!(f, "{}", i),
U8(i) => write!(f, "{}", i),
U64(i) => write!(f, "{}", i),
I64(i) => write!(f, "{}", i),
F32(i) => write!(f, "{}", i),
F64(i) => write!(f, "{}", i),
U128(i) => write!(f, "{}", i),
I128(i) => write!(f, "{}", i),
String(i) => write!(f, "{}", i),
Bytes(i) => write!(f, "{}", std::string::String::from_utf8_lossy(i)),
Null => write!(f, "null",),
Vec(i) => write!(f, "{:?}", i),
EnumNumber(i) => write!(f, "{:?}", i),
Map(i) => write!(f, "{:?}", i),
}
}
}
impl DataValue {
pub fn extract<T>(&self) -> T
where
T: Extract,
{
T::extract(self)
}
pub fn extract_bytes(&self) -> Vec<u8> {
match self {
DataValue::Bytes(i) => i.to_vec(),
_ => vec![],
}
}
}
pub trait Extract {
fn extract(v: &DataValue) -> Self;
}
impl DataValue {
pub fn contains(&self, other: &str) -> bool {
match self {
DataValue::Vec(v) => v.iter().any(|x| x.contains(other)),
DataValue::Map(v) => v.keys().any(|x| x.contains(other)),
DataValue::String(v) => v.contains(other),
_ => false,
}
}
}
pub fn convert<D: Extract>(data: &[DataValue]) -> Vec<D> {
let mut result = Vec::with_capacity(data.len());
for d in data {
result.push(D::extract(d));
}
result
}
#[macro_export]
macro_rules! datavalue {
($(vec![$($value:expr),*]),*) => {
$crate::datavalue!($([$($value),*]),*)
};
($([$($value:expr),*]),*) => {
{
$(
let mut _vec = Vec::new();
$(
_vec.push($crate::DataValue::from($value));
)*
$crate::DataValue::Vec(_vec)
)*
}
};
($($key:expr => $value:expr,)+) => { $crate::datavalue!($($key => $value),+) };
($($key:expr => vec![$($value:expr),*]),*) => {
$crate::datavalue!($($key => [$($value),*]),*)
};
($($key:expr => [$($value:expr),*]),*) => {
{
let mut _map = ::std::collections::HashMap::new();
$(
let mut _arr = Vec::new();
$(
_arr.push($value.into());
)*
_map.insert($key.into(), $crate::DataValue::Vec(_arr));
)*
$crate::DataValue::Map(_map)
}
};
($($key:expr => $value:expr),*) => {
{
let mut _map = ::std::collections::HashMap::new();
$(
_map.insert($key.into(), $value.into());
)*
$crate::DataValue::Map(_map)
}
};
($value:expr) => {
$crate::DataValue::from($value)
};
}
#[cfg(test)]
mod test {
use std::fmt::Debug;
use super::*;
use rstest::*;
#[test]
fn from_json_object_to_datavalue() {
let value = DataValue::from(&serde_json::json!(12));
assert_eq!(value, DataValue::I64(12));
let value = DataValue::from(&serde_json::json!(12.0));
assert_eq!(value, DataValue::F64(12.0));
let value = DataValue::from(&serde_json::json!("12"));
assert_eq!(value, DataValue::String("12".into()));
let value = DataValue::from(&serde_json::json!(true));
assert_eq!(value, DataValue::Bool(true));
let value = DataValue::from(&serde_json::json!(false));
assert_eq!(value, DataValue::Bool(false));
let value = DataValue::from(&serde_json::json!(null));
assert_eq!(value, DataValue::Null);
}
#[test]
fn from_native_to_datavalue() {
let value = DataValue::from(12u32);
assert_eq!(value, DataValue::U32(12));
let value = DataValue::from(12.0f64);
assert_eq!(value, DataValue::F64(12.0));
let value = DataValue::from("12");
assert_eq!(value, DataValue::String("12".into()));
let value = DataValue::from(true);
assert_eq!(value, DataValue::Bool(true));
let value = DataValue::from(false);
assert_eq!(value, DataValue::Bool(false));
let value = DataValue::from(());
assert_eq!(value, DataValue::Null);
}
#[rstest]
#[case(DataValue::U32(12), 12u32)]
#[case(DataValue::I32(12), 12i32)]
#[case(DataValue::U8(12), 12u8)]
#[case(DataValue::U64(12), 12u64)]
#[case(DataValue::I64(12), 12i64)]
#[case(DataValue::F32(12.0), 12f32)]
#[case(DataValue::F64(12.0), 12f64)]
#[case(DataValue::U128(12), 12u128)]
#[case(DataValue::I128(12), 12i128)]
#[case(DataValue::String("12".into()), "12".to_string())]
#[case(DataValue::Bool(true), true)]
#[case(DataValue::Bool(false), false)]
fn as_data_value_test<T: PartialEq + std::fmt::Debug + Into<DataValue> + Extract>(
#[case] value: DataValue,
#[case] expected: T,
) {
assert_eq!(value.extract::<T>(), expected);
assert_eq!(value, expected.into());
}
#[rstest]
#[case(DataValue::Bytes("12".as_bytes().to_vec()), "12".as_bytes().to_vec())]
fn as_data_value_test_bytes(#[case] value: DataValue, #[case] expected: Vec<u8>) {
assert_eq!(value.extract_bytes(), expected);
}
#[rstest]
#[case(DataValue::U32(12), DataValue::U32(12), true)]
#[case(DataValue::I32(12), DataValue::I32(12), true)]
#[case(DataValue::U8(12), DataValue::U8(12), true)]
#[case(DataValue::U64(12), DataValue::U64(12), true)]
#[case(DataValue::I64(12), DataValue::I64(12), true)]
#[case(DataValue::F32(12.0), DataValue::F32(12.0), true)]
#[case(DataValue::F64(12.0), DataValue::F64(12.0), true)]
#[case(DataValue::U128(12), DataValue::U128(12), true)]
#[case(DataValue::I128(12), DataValue::I128(12), true)]
#[case(DataValue::String("12".into()), DataValue::String("12".into()), true)]
#[case(DataValue::Bytes("12".as_bytes().to_vec()), DataValue::Bytes("12".as_bytes().to_vec()), true)]
#[case(DataValue::Bool(true), DataValue::Bool(true), true)]
#[case(DataValue::Bool(false), DataValue::Bool(false), true)]
fn eq_test(#[case] value: DataValue, #[case] other: DataValue, #[case] expected: bool) {
assert_eq!(value == other, expected);
print!("{} == {} = {}", value, other, expected);
}
#[rstest]
#[case(
crate::datavalue!(1u32),
DataValue::U32(1),
vec![1u32]
)]
#[case(
crate::datavalue!(vec![1u32, 2u32]),
DataValue::Vec(vec![DataValue::U32(1), DataValue::U32(2)]),
vec![vec![1u32, 2u32]]
)]
fn convert_test<T: Extract + PartialEq + Debug>(
#[case] value: DataValue,
#[case] expected: DataValue,
#[case] expected_native: Vec<T>,
) {
assert_eq!(value, expected);
let converted: Vec<T> = convert::<T>(&[value]);
assert_eq!(converted, expected_native);
}
}