use rbs::Value;
use serde::de::DeserializeOwned;
use crate::Error;
pub fn decode_ref<T>(values: &Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
match values {
Value::Array(_) => {
match rbs::from_value_ref::<T>(values) {
Ok(v) => Ok(v),
Err(e) => match try_decode_single_column(values) {
Ok(v) => Ok(v),
Err(Some(fallback_err)) => Err(fallback_err),
Err(None) => Err(e.into()),
},
}
}
_ => Err(Error::from("decode error: expected array value")),
}
}
pub fn decode<T>(bs: Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
decode_ref(&bs)
}
pub fn try_decode_elements<T: DeserializeOwned>(datas: &Value) -> Result<T, Error> {
try_decode_single_column(datas).map_err(|e| {
e.unwrap_or_else(|| Error::from("decode error: unsupported single row struct decode"))
})
}
fn try_decode_single_column<T: DeserializeOwned>(datas: &Value) -> Result<T, Option<Error>> {
let items = match datas {
Value::Array(items) => items,
_ => return rbs::from_value_ref::<T>(datas).map_err(|e| Some(e.into())),
};
let mut last_err = None;
for item in items {
let inner = match item {
Value::Map(m) if m.len() == 1 => m.into_iter().next().map(|(_, v)| v),
Value::Array(a) if a.len() == 1 => Some(&a[0]),
_ => None,
};
if let Some(v) = inner {
if let Ok(r) = rbs::from_value_ref::<T>(v) {
return Ok(r);
}
last_err = rbs::from_value_ref::<T>(v).err().map(Error::from);
}
}
Err(last_err)
}
pub fn is_debug_mode() -> bool {
cfg!(all(debug_assertions, feature = "debug_mode"))
}