use std::ops::Index;
use rbs::{Value};
use serde::de::DeserializeOwned;
use crate::Error;
pub fn decode_ref<T: ?Sized>(values: &Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
match values {
Value::Array(_) => {
let direct_result = rbs::from_value_ref::<T>(values);
if direct_result.is_ok() {
return direct_result;
}
try_decode_map(values)
}
_ => {
Err(Error::from("decode an not array value"))
}
}
}
pub fn decode<T: ?Sized>(bs: Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
decode_ref(&bs)
}
pub fn try_decode_map<T>(datas: &Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
if datas.len() > 2 {
return Err(Error::from(format!(
"[rb] rows.rows_affected > 1,but decode one type ({})!",
std::any::type_name::<T>()
)));
}
if datas.len() <= 1 {
return Ok(rbs::from_value::<T>(Value::Null)?);
}
let values = datas.index(1);
match values {
Value::Array(arr) => {
if arr.len() == 1 {
let type_name = std::any::type_name::<T>();
if type_name == std::any::type_name::<i32>()
|| type_name == std::any::type_name::<i64>()
|| type_name == std::any::type_name::<f32>()
|| type_name == std::any::type_name::<f64>()
|| type_name == std::any::type_name::<u32>()
|| type_name == std::any::type_name::<u64>()
|| type_name == std::any::type_name::<String>()
|| type_name == std::any::type_name::<bool>()
|| type_name == std::any::type_name::<Option<i32>>()
|| type_name == std::any::type_name::<Option<i64>>()
|| type_name == std::any::type_name::<Option<f32>>()
|| type_name == std::any::type_name::<Option<f64>>()
|| type_name == std::any::type_name::<Option<u32>>()
|| type_name == std::any::type_name::<Option<u64>>()
|| type_name == std::any::type_name::<Option<String>>()
|| type_name == std::any::type_name::<Option<bool>>()
|| type_name.starts_with("rbdc::types::")
|| type_name.starts_with("core::option::Option<rbdc::types::")
{
if let Some(value) = arr.into_iter().next() {
return Ok(rbs::from_value_ref::<T>(value)?);
}
}
}
}
_ => {}
}
let arr = rbs::from_value_ref::<Vec<T>>(datas)?;
arr.into_iter().next().ok_or_else(||Error::from("fail type"))
}
pub fn is_debug_mode() -> bool {
if cfg!(debug_assertions) {
#[cfg(feature = "debug_mode")]
{
true
}
#[cfg(not(feature = "debug_mode"))]
{
false
}
} else {
false
}
}