rbatis_core/
decode.rs

1//! Types and traits for decoding values from the database.
2use rbson::Bson;
3use log::info;
4use serde::de::DeserializeOwned;
5
6use crate::{Error};
7use crate::Error::E;
8use crate::types::Format;
9
10/// decode json vec to an object
11/// support decode types:
12/// Bson,BigDecimal, i8..i64,u8..u64,rbson::Int64(),bool,String
13/// or object used bson macro object
14pub fn decode<T: ?Sized>(datas: rbson::Array) -> Result<T, crate::Error>
15    where
16        T: DeserializeOwned,
17{
18    let type_name = std::any::type_name::<T>();
19    //debug_mode feature print json_decode json data
20    let bs = Bson::Array(datas);
21    #[cfg(feature = "debug_mode")]
22        {
23            println!("[rbatis] [debug_mode] [bson]   {} => {}", type_name, bs);
24            #[cfg(feature = "format_bson")]
25            println!("[rbatis] [debug_mode] [format] {} => {}", type_name, bs.as_array().unwrap().do_format());
26        }
27    let mut datas = vec![];
28    match bs {
29        Bson::Array(arr) => {
30            datas = arr;
31        }
32        _ => {}
33    }
34    // Hit a non-array object
35    match type_name {
36        //decode single type option
37        "core::option::Option<i8>" | "core::option::Option<i16>" | "core::option::Option<i32>" | "core::option::Option<i64>" |
38        "core::option::Option<u8>" | "core::option::Option<u16>" | "core::option::Option<u32>" | "core::option::Option<u64>" |
39        "core::option::Option<f32>" | "core::option::Option<f64>" |
40        "core::option::Option<serde_json::number::Number>" |
41        "core::option::Option<rbson::Bson::Int64>" | "core::option::Option<rbson::Bson::Int32>" | "core::option::Option<rbson::Bson::Double>" |
42        "core::option::Option<bigdecimal::BigDecimal>" |
43        "core::option::Option<bool>" |
44        "core::option::Option<alloc::string::String>" |
45        //decode single type(from map type get an value)
46        "i8" | "i16" | "i32" | "i64" |
47        "u8" | "u16" | "u32" | "u64" |
48        "f32" | "f64" |
49        "serde_json::number::Number" |
50        "rbson::Bson::Int64" | "rbson::Bson::Int32" | "rbson::Bson::Double" |
51        "bigdecimal::BigDecimal" |
52        "bool" |
53        "alloc::string::String" => {
54            return Ok(try_decode_doc(type_name, &mut datas)?);
55        }
56        _ => {}
57    }
58    // try speculate type
59    let is_array: Result<T, rbson::de::Error> = rbson::from_bson(rbson::Bson::Array(vec![]));
60    if is_array.is_ok() {
61        //decode array
62        Ok(rbson::from_bson(Bson::Array(datas))?)
63    } else {
64        Ok(try_decode_doc(type_name, &mut datas)?)
65    }
66}
67
68//decode doc or one type
69pub fn try_decode_doc<T>(type_name: &str, datas: &mut Vec<Bson>) -> Result<T, crate::Error>
70    where
71        T: DeserializeOwned, {
72    //decode struct
73    if datas.len() > 1 {
74        return Result::Err(Error::from(format!("[rbatis] rows.rows_affected > 1,but decode one type ({})!", type_name)));
75    }
76    //single try decode
77    if datas.is_empty() {
78        return Ok(rbson::from_bson::<T>(Bson::Null)?);
79    }
80    let mut v = Bson::Null;
81    let m = datas.remove(0);
82    let mut doc_len = 0;
83    match &m {
84        Bson::Document(doc) => {
85            doc_len = doc.len();
86            if doc_len == 1 {
87                for (_k, _v) in doc {
88                    v = _v.clone();
89                    break;
90                }
91            }
92        }
93        _ => {}
94    }
95    let r = rbson::from_bson::<T>(m);
96    if r.is_err() {
97        if doc_len > 1 {
98            return Ok(r?);
99        }
100        //try one
101        return Ok(rbson::from_bson::<T>(v)?);
102    } else {
103        return Ok(r.unwrap());
104    }
105}
106
107
108#[cfg(test)]
109mod test {
110    use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
111    use rbson::Bson;
112    use rbson::bson;
113    use crate::decode::{decode};
114    use crate::types::Json;
115
116    #[test]
117    fn test_decode_hashmap() {
118        let m: HashMap<String, Bson> = decode(vec![bson!(
119        {
120        "a":"1",
121        "b":2
122        }
123        )])
124            .unwrap();
125        println!("{:#?}", m);
126    }
127
128    #[test]
129    fn test_decode_btree_map() {
130        let m: BTreeMap<String, Bson> = decode(vec![bson!(
131        {
132        "a":"1",
133        "b":2
134        }
135        )])
136            .unwrap();
137        println!("{:#?}", m);
138    }
139}