denizzzka / dpq2
1
///
2
module dpq2.conv.from_bson;
3

4
import dpq2.value;
5
import dpq2.oids;
6
import dpq2.result: ArrayProperties, ArrayHeader_net, Dim_net;
7
import dpq2.conv.from_d_types;
8
import dpq2.conv.to_d_types;
9
import vibe.data.bson;
10
import std.bitmanip: nativeToBigEndian;
11
import std.conv: to;
12

13
/// Default type will be used for NULL value and for array without detected type
14
Value bsonToValue(Bson v, OidType defaultType = OidType.Undefined)
15
{
16 1
    if(v.type == Bson.Type.array)
17 1
        return bsonArrayToValue(v, defaultType);
18
    else
19 1
        return bsonValueToValue(v, defaultType);
20
}
21

22
private:
23

24
Value bsonValueToValue(Bson v, OidType defaultType)
25
{
26 1
    Value ret;
27

28
    with(Bson.Type)
29 1
    switch(v.type)
30
    {
31 0
        case null_:
32 0
            ret = Value(ValueFormat.BINARY, defaultType);
33 0
            break;
34

35 0
        case Bson.Type.object:
36 0
            ret = v.toJson.toString.toValue;
37 0
            ret.oidType = OidType.Json;
38 0
            break;
39

40 1
        case bool_:
41 1
            ret = v.get!bool.toValue;
42 1
            break;
43

44 1
        case int_:
45 1
            ret = v.get!int.toValue;
46 1
            break;
47

48 0
        case long_:
49 0
            ret = v.get!long.toValue;
50 0
            break;
51

52 0
        case double_:
53 0
            ret = v.get!double.toValue;
54 0
            break;
55

56 1
        case Bson.Type.string:
57 1
            ret = v.get!(immutable(char)[]).toValue;
58 1
            break;
59

60 0
        default:
61 0
            throw new ValueConvException(
62
                    ConvExceptionType.NOT_IMPLEMENTED,
63
                    "Format "~v.type.to!(immutable(char)[])~" doesn't supported by Bson to Value converter",
64
                    __FILE__, __LINE__
65
                );
66
    }
67

68 1
    return ret;
69
}
70

71
unittest
72
{
73
    {
74 1
        Value v1 = bsonToValue(Bson(123));
75 1
        Value v2 = (123).toValue;
76

77 1
        assert(v1.as!int == v2.as!int);
78
    }
79

80
    {
81 1
        Value v1 = bsonToValue(Bson("Test string"));
82 1
        Value v2 = ("Test string").toValue;
83

84 1
        assert(v1.as!string == v2.as!string);
85
    }
86

87
    {
88 1
        Value t = bsonToValue(Bson(true));
89 1
        Value f = bsonToValue(Bson(false));
90

91 1
        assert(t.as!bool == true);
92 1
        assert(f.as!bool == false);
93
    }
94
}
95

96
Value bsonArrayToValue(ref Bson bsonArr, OidType defaultType)
97
{
98
    ubyte[] nullValue() pure
99
    {
100 1
        ubyte[] ret = [0xff, 0xff, 0xff, 0xff]; //NULL magic number
101 1
        return ret;
102
    }
103

104
    ubyte[] rawValue(Value v) pure
105
    {
106 1
        if(v.isNull)
107
        {
108 0
            return nullValue();
109
        }
110
        else
111
        {
112 1
            return v._data.length.to!uint.nativeToBigEndian ~ v._data;
113
        }
114
    }
115

116 1
    ArrayProperties ap;
117 1
    ubyte[] rawValues;
118

119
    void recursive(ref Bson bsonArr, int dimension)
120
    {
121 1
        if(dimension == ap.dimsSize.length)
122
        {
123 1
            ap.dimsSize ~= bsonArr.length.to!int;
124
        }
125
        else
126
        {
127 1
            if(ap.dimsSize[dimension] != bsonArr.length)
128 1
                throw new ValueConvException(ConvExceptionType.NOT_ARRAY, "Jagged arrays are unsupported", __FILE__, __LINE__);
129
        }
130

131 1
        foreach(bElem; bsonArr)
132
        {
133 1
            ap.nElems++;
134

135 1
            switch(bElem.type)
136
            {
137 1
                case Bson.Type.array:
138 1
                    recursive(bElem, dimension + 1);
139 1
                    break;
140

141 1
                case Bson.Type.null_:
142 1
                    rawValues ~= nullValue();
143 1
                    break;
144

145 1
                default:
146 1
                    Value v = bsonValueToValue(bElem, OidType.Undefined);
147

148 1
                    if(ap.OID == OidType.Undefined)
149
                    {
150 1
                        ap.OID = v.oidType;
151
                    }
152
                    else
153
                    {
154 1
                        if(ap.OID != v.oidType)
155 0
                            throw new ValueConvException(
156
                                    ConvExceptionType.NOT_ARRAY,
157
                                    "Bson (which used for creating "~ap.OID.to!string~" array) also contains value of type "~v.oidType.to!string,
158
                                    __FILE__, __LINE__
159
                                );
160
                    }
161

162 1
                    rawValues ~= rawValue(v);
163
            }
164
        }
165
    }
166

167 1
    recursive(bsonArr, 0);
168

169 1
    if(ap.OID == OidType.Undefined) ap.OID = defaultType.oidConvTo!"element";
170

171 1
    ArrayHeader_net h;
172 1
    h.ndims = nativeToBigEndian(ap.dimsSize.length.to!int);
173 1
    h.OID = nativeToBigEndian(ap.OID.to!Oid);
174

175 1
    ubyte[] ret;
176 1
    ret ~= (cast(ubyte*) &h)[0 .. h.sizeof];
177

178 1
    foreach(i; 0 .. ap.dimsSize.length)
179
    {
180 1
        Dim_net dim;
181 1
        dim.dim_size = nativeToBigEndian(ap.dimsSize[i]);
182 1
        dim.lbound = nativeToBigEndian!int(1);
183

184 1
        ret ~= (cast(ubyte*) &dim)[0 .. dim.sizeof];
185
    }
186

187 1
    ret ~= rawValues;
188

189 1
    return Value(cast(immutable) ret, ap.OID.oidConvTo!"array", false, ValueFormat.BINARY);
190
}
191

192
unittest
193
{
194
    import dpq2.conv.to_bson;
195

196
    {
197 1
        Bson bsonArray = Bson(
198
            [Bson(123), Bson(155), Bson(null), Bson(0), Bson(null)]
199
        );
200

201 1
        Value v = bsonToValue(bsonArray);
202

203 1
        assert(v.isSupportedArray);
204 1
        assert(v.as!Bson == bsonArray);
205
    }
206

207
    {
208 1
        Bson bsonArray = Bson([
209
            Bson([Bson(123), Bson(155), Bson(null)]),
210
            Bson([Bson(0), Bson(null), Bson(155)])
211
        ]);
212

213 1
        Value v = bsonToValue(bsonArray);
214

215 1
        assert(v.isSupportedArray);
216 1
        assert(v.as!Bson == bsonArray);
217
    }
218

219
    {
220 1
        Bson bsonArray = Bson([
221
            Bson([Bson(123), Bson(155)]),
222
            Bson([Bson(0)])
223
        ]);
224

225 1
        bool exceptionFlag = false;
226

227
        try
228 1
            bsonToValue(bsonArray);
229
        catch(ValueConvException e)
230
        {
231 1
            if(e.type == ConvExceptionType.NOT_ARRAY)
232 1
                exceptionFlag = true;
233
        }
234

235 1
        assert(exceptionFlag);
236
    }
237
}

Read our documentation on viewing source code .

Loading