1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Types and traits for decoding values from the database.
use rbson::Bson;
use log::info;
use serde::de::DeserializeOwned;

use crate::{Error};
use crate::Error::E;
use crate::types::Format;

/// decode json vec to an object
/// support decode types:
/// Bson,BigDecimal, i8..i64,u8..u64,rbson::Int64(),bool,String
/// or object used bson macro object
pub fn decode<T: ?Sized>(datas: rbson::Array) -> Result<T, crate::Error>
    where
        T: DeserializeOwned,
{
    let type_name = std::any::type_name::<T>();
    //debug_mode feature print json_decode json data
    let bs = Bson::Array(datas);
    #[cfg(feature = "debug_mode")]
        {
            println!("[mybatis] [debug_mode] [bson]   {} => {}", type_name, bs);
            #[cfg(feature = "format_bson")]
            println!("[mybatis] [debug_mode] [format] {} => {}", type_name, bs.as_array().unwrap().do_format());
        }
    let mut datas = vec![];
    match bs {
        Bson::Array(arr) => {
            datas = arr;
        }
        _ => {}
    }
    // Hit a non-array object
    match type_name {
        //decode single type option
        "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>" |
        //decode single type(from map type get an value)
        "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)?);
        }
        _ => {}
    }
    // try speculate type
    let is_array: Result<T, rbson::de::Error> = rbson::from_bson(rbson::Bson::Array(vec![]));
    if is_array.is_ok() {
        //decode array
        Ok(rbson::from_bson(Bson::Array(datas))?)
    } else {
        Ok(try_decode_doc(type_name, &mut datas)?)
    }
}

//decode doc or one type
pub fn try_decode_doc<T>(type_name: &str, datas: &mut Vec<Bson>) -> Result<T, crate::Error>
    where
        T: DeserializeOwned, {
    //decode struct
    if datas.len() > 1 {
        return Result::Err(Error::from(format!("[mybatis] rows.rows_affected > 1,but decode one type ({})!", type_name)));
    }
    //single try decode
    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?);
        }
        //try one
        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);
    }
}