use rbson::Bson;
use log::info;
use serde::de::DeserializeOwned;
use crate::{Error};
use crate::Error::E;
use crate::types::Format;
pub fn decode<T: ?Sized>(datas: rbson::Array) -> Result<T, crate::Error>
where
T: DeserializeOwned,
{
let type_name = std::any::type_name::<T>();
let bs = Bson::Array(datas);
#[cfg(feature = "debug_mode")]
{
println!("[rbatis] [debug_mode] [bson] {} => {}", type_name, bs);
#[cfg(feature = "format_bson")]
println!("[rbatis] [debug_mode] [format] {} => {}", type_name, bs.as_array().unwrap().do_format());
}
let mut datas = vec![];
match bs {
Bson::Array(arr) => {
datas = arr;
}
_ => {}
}
match type_name {
"core::option::Option<i8>" | "core::option::Option<i16>" | "core::option::Option<i32>" | "core::option::Option<i64>" |
"core::option::Option<u8>" | "core::option::Option<u16>" | "core::option::Option<u32>" | "core::option::Option<u64>" |
"core::option::Option<f32>" | "core::option::Option<f64>" |
"core::option::Option<serde_json::number::Number>" |
"core::option::Option<rbson::Bson::Int64>" | "core::option::Option<rbson::Bson::Int32>" | "core::option::Option<rbson::Bson::Double>" |
"core::option::Option<bigdecimal::BigDecimal>" |
"core::option::Option<bool>" |
"core::option::Option<alloc::string::String>" |
"i8" | "i16" | "i32" | "i64" |
"u8" | "u16" | "u32" | "u64" |
"f32" | "f64" |
"serde_json::number::Number" |
"rbson::Bson::Int64" | "rbson::Bson::Int32" | "rbson::Bson::Double" |
"bigdecimal::BigDecimal" |
"bool" |
"alloc::string::String" => {
return Ok(try_decode_doc(type_name, &mut datas)?);
}
_ => {}
}
let is_array: Result<T, rbson::de::Error> = rbson::from_bson(rbson::Bson::Array(vec![]));
if is_array.is_ok() {
Ok(rbson::from_bson(Bson::Array(datas))?)
} else {
Ok(try_decode_doc(type_name, &mut datas)?)
}
}
pub fn try_decode_doc<T>(type_name: &str, datas: &mut Vec<Bson>) -> Result<T, crate::Error>
where
T: DeserializeOwned, {
if datas.len() > 1 {
return Result::Err(Error::from(format!("[rbatis] rows.rows_affected > 1,but decode one type ({})!", type_name)));
}
if datas.is_empty() {
return Ok(rbson::from_bson::<T>(Bson::Null)?);
}
let mut v = Bson::Null;
let m = datas.remove(0);
let mut doc_len = 0;
match &m {
Bson::Document(doc) => {
doc_len = doc.len();
if doc_len == 1 {
for (_k, _v) in doc {
v = _v.clone();
break;
}
}
}
_ => {}
}
let r = rbson::from_bson::<T>(m);
if r.is_err() {
if doc_len > 1 {
return Ok(r?);
}
return Ok(rbson::from_bson::<T>(v)?);
} else {
return Ok(r.unwrap());
}
}
#[cfg(test)]
mod test {
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use rbson::Bson;
use rbson::bson;
use crate::decode::{decode};
use crate::types::Json;
#[test]
fn test_decode_hashmap() {
let m: HashMap<String, Bson> = decode(vec![bson!(
{
"a":"1",
"b":2
}
)])
.unwrap();
println!("{:#?}", m);
}
#[test]
fn test_decode_btree_map() {
let m: BTreeMap<String, Bson> = decode(vec![bson!(
{
"a":"1",
"b":2
}
)])
.unwrap();
println!("{:#?}", m);
}
}