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
//! Types and traits for decoding values from the database.
use bson::Bson;
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,bson::Int64(),bool,String
/// or object used bson macro object
pub fn decode<T: ?Sized>(mut datas: Vec<Bson>) -> Result<T, crate::Error>
    where
        T: DeserializeOwned,
{
    let mut js = Bson::Null;
    let mut type_name = std::any::type_name::<T>();
    //debug_mode feature print json_decode json data
    #[cfg(feature = "debug_mode")]
    println!("[rbatis] [debug_mode] {} => {}", type_name, datas.do_format());

    // 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<bson::Bson::Int64>" | "core::option::Option<bson::Bson::Int32>" | "core::option::Option<bson::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" |
        "bson::Bson::Int64" | "bson::Bson::Int32" | "bson::Bson::Double" |
        "bigdecimal::BigDecimal" |
        "bool" |
        "alloc::string::String" => {
            return Ok(decode_one(type_name, &mut datas)?);
        }
        _ => {

        }
    }
    // try speculate type
    let is_array: Result<T, bson::de::Error> = bson::from_bson(bson::Bson::Array(vec![]));
    if is_array.is_ok() {
        //decode array
        js = Bson::Array(datas);
        return Ok(bson::from_bson(js)?);
    } else {
        Ok(decode_one(type_name, &mut datas)?)
    }
}

pub fn decode_one<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!("[rbatis] rows.rows_affected > 1,but decode one type ({})!", type_name)));
    }
    //single try decode
    if datas.is_empty() {
        return Ok(bson::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 = bson::from_bson::<T>(m);
    if r.is_err() {
        if doc_len > 1 {
            return Ok(r?);
        }
        //try one
        return Ok(bson::from_bson::<T>(v)?);
    } else {
        return Ok(r.unwrap());
    }
}


#[cfg(test)]
mod test {
    use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
    use bson::Bson;
    use bson::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);
    }
}