mybatis_core/
decode.rs

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