denizzzka / dpq2

@@ -21,7 +21,7 @@
Loading
21 21
import std.datetime;
22 22
import std.traits: isScalarType;
23 23
import std.typecons : Nullable;
24 -
import std.bitmanip: bigEndianToNative;
24 +
import std.bitmanip: bigEndianToNative, BitArray;
25 25
import std.conv: to;
26 26
version (unittest) import std.exception : assertThrown;
27 27
@@ -42,6 +42,7 @@
Loading
42 42
alias PGtimestamptz = TimeStampUTC; /// Both date and time stored in UTC time zone
43 43
alias PGjson =          Json; /// json or jsonb
44 44
alias PGline =          Line; /// Line (geometric type)
45 +
alias PGvarbit =        BitArray; /// BitArray
45 46
46 47
private alias VF = ValueFormat;
47 48
private alias AE = ValueConvException;
@@ -314,3 +315,46 @@
Loading
314 315
    auto v = Value([1], OidType.Money);
315 316
    assertThrown!ValueConvException(v.binaryValueAs!PGTestMoney);
316 317
}
318 +
319 +
T binaryValueAs(T)(in Value v) @trusted
320 +
if( is(T == BitArray) )
321 +
{
322 +
    import core.bitop : bitswap;
323 +
    import std.bitmanip;
324 +
    import std.format: format;
325 +
    import std.range : chunks;
326 +
327 +
    if(v.data.length < int.sizeof)
328 +
        throw new AE(
329 +
            ET.SIZE_MISMATCH,
330 +
            format(
331 +
                "%s length (%d) is less than minimum int type size (%d)",
332 +
                v.oidType.to!string,
333 +
                v.data.length,
334 +
                int.sizeof
335 +
            )
336 +
        );
337 +
338 +
    auto data = v.data;
339 +
    size_t len = data.read!int;
340 +
    size_t[] newData;
341 +
    foreach (ch; data.chunks(size_t.sizeof))
342 +
    {
343 +
        ubyte[size_t.sizeof] tmpData;
344 +
        tmpData[0 .. ch.length] = ch[];
345 +
346 +
        // DMD Issue 19693
347 +
        version(DigitalMars)
348 +
            auto re = softBitswap(bigEndianToNative!size_t(tmpData));
349 +
        else
350 +
            auto re = bitswap(bigEndianToNative!size_t(tmpData));
351 +
        newData ~= re;
352 +
    }
353 +
    return T(newData, len);
354 +
}
355 +
356 +
unittest
357 +
{
358 +
    auto v = Value([1], OidType.VariableBitString);
359 +
    assertThrown!ValueConvException(v.binaryValueAs!BitArray);
360 +
}

@@ -9,7 +9,7 @@
Loading
9 9
import dpq2.oids : detectOidTypeFromNative, oidConvTo, OidType;
10 10
import dpq2.value : Value, ValueFormat;
11 11
12 -
import std.bitmanip: nativeToBigEndian;
12 +
import std.bitmanip: nativeToBigEndian, BitArray, append;
13 13
import std.datetime.date: Date, DateTime, TimeOfDay;
14 14
import std.datetime.systime: SysTime;
15 15
import std.datetime.timezone: LocalTime, TimeZone, UTC;
@@ -71,6 +71,80 @@
Loading
71 71
    assert(v.as!PGTestMoney == pgtm);
72 72
}
73 73
74 +
/// Convert std.bitmanip.BitArray to PG value
75 +
Value toValue(T)(T v) @trusted
76 +
if(is(Unqual!T == BitArray))
77 +
{
78 +
    import std.array : appender;
79 +
    import core.bitop : bitswap;
80 +
81 +
    size_t len = v.length / 8 + (v.length % 8 ? 1 : 0);
82 +
    auto data = cast(size_t[])v;
83 +
    auto buffer = appender!(const ubyte[])();
84 +
    buffer.append!uint(cast(uint)v.length);
85 +
    foreach (d; data[0 .. v.dim])
86 +
    {
87 +
        // DMD Issue 19693
88 +
        version(DigitalMars)
89 +
            auto ntb = nativeToBigEndian(softBitswap(d));
90 +
        else
91 +
            auto ntb = nativeToBigEndian(bitswap(d));
92 +
        foreach (b; ntb[0 .. len])
93 +
        {
94 +
            buffer.append!ubyte(b);
95 +
        }
96 +
97 +
    }
98 +
    return Value(buffer.data.dup, detectOidTypeFromNative!T, false, ValueFormat.BINARY);
99 +
}
100 +
101 +
/// Reverses the order of bits - needed because of dmd Issue 19693
102 +
/// https://issues.dlang.org/show_bug.cgi?id=19693
103 +
package N softBitswap(N)(N x) pure
104 +
    if (is(N == uint) || is(N == ulong))
105 +
{
106 +
    import core.bitop : bswap;
107 +
    // swap 1-bit pairs:
108 +
    enum mask1 = cast(N) 0x5555_5555_5555_5555L;
109 +
    x = ((x >> 1) & mask1) | ((x & mask1) << 1);
110 +
    // swap 2-bit pairs:
111 +
    enum mask2 = cast(N) 0x3333_3333_3333_3333L;
112 +
    x = ((x >> 2) & mask2) | ((x & mask2) << 2);
113 +
    // swap 4-bit pairs:
114 +
    enum mask4 = cast(N) 0x0F0F_0F0F_0F0F_0F0FL;
115 +
    x = ((x >> 4) & mask4) | ((x & mask4) << 4);
116 +
117 +
    // reverse the order of all bytes:
118 +
    x = bswap(x);
119 +
120 +
    return x;
121 +
}
122 +
123 +
@trusted unittest
124 +
{
125 +
    import std.bitmanip : BitArray;
126 +
127 +
    auto varbit = BitArray([1,0,1,1,0]);
128 +
129 +
    Value v = varbit.toValue;
130 +
131 +
    assert(v.oidType == OidType.VariableBitString);
132 +
    assert(v.as!BitArray == varbit);
133 +
134 +
    // test softBitswap
135 +
    assert (softBitswap!uint( 0x8000_0100 ) == 0x0080_0001);
136 +
    foreach (i; 0 .. 32)
137 +
        assert (softBitswap!uint(1 << i) == 1 << 32 - i - 1);
138 +
139 +
    assert (softBitswap!ulong( 0b1000000000000000000000010000000000000000100000000000000000000001)
140 +
            == 0b1000000000000000000000010000000000000000100000000000000000000001);
141 +
    assert (softBitswap!ulong( 0b1110000000000000000000010000000000000000100000000000000000000001)
142 +
        == 0b1000000000000000000000010000000000000000100000000000000000000111);
143 +
    foreach (i; 0 .. 64)
144 +
        assert (softBitswap!ulong(1UL << i) == 1UL << 64 - i - 1);
145 +
146 +
}
147 +
74 148
/**
75 149
    Converts types implicitly convertible to string to PG Value.
76 150
    Note that if string is null it is written as an empty string.

@@ -3,6 +3,7 @@
Loading
3 3
import dpq2;
4 4
import dpq2.conv.arrays : isArrayType;
5 5
import dpq2.conv.geometric: Line;
6 +
import std.bitmanip : BitArray;
6 7
import std.datetime;
7 8
import std.typecons: Nullable;
8 9
import std.uuid: UUID;
@@ -128,6 +129,9 @@
Loading
128 129
            "bytea", r"E'\\x44 20 72 75 6c 65 73 00 21'"); // "D rules\x00!" (ASCII)
129 130
        C!PGuuid(UUID("8b9ab33a-96e9-499b-9c36-aad1fe86d640"), "uuid", "'8b9ab33a-96e9-499b-9c36-aad1fe86d640'");
130 131
        C!(Nullable!PGuuid)(Nullable!UUID(UUID("8b9ab33a-96e9-499b-9c36-aad1fe86d640")), "uuid", "'8b9ab33a-96e9-499b-9c36-aad1fe86d640'");
132 +
        C!PGvarbit(BitArray([1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1]), "varbit", "'101011010110101'");
133 +
        C!PGvarbit(BitArray([0, 0, 1, 0, 1]), "varbit", "'00101'");
134 +
        C!PGvarbit(BitArray([1, 0, 1, 0, 0]), "varbit", "'10100'");
131 135
132 136
        // numeric testing
133 137
        C!PGnumeric("NaN", "numeric", "'NaN'");

@@ -167,6 +167,7 @@
Loading
167 167
168 168
private OidType detectOidTypeNotCareAboutNullable(T)()
169 169
{
170 +
    import std.bitmanip : BitArray;
170 171
    import std.datetime.date : StdDate = Date, TimeOfDay, DateTime;
171 172
    import std.datetime.systime : SysTime;
172 173
    import std.traits : Unqual;
@@ -194,6 +195,7 @@
Loading
194 195
        static if(is(UT == dpq2.conv.time.TimeStampUTC)){ return TimeStampWithZone; } else
195 196
        static if(is(UT == VibeJson)){ return Json; } else
196 197
        static if(is(UT == StdUUID)){ return UUID; } else
198 +
        static if(is(UT == BitArray)){ return VariableBitString; } else
197 199
198 200
        static assert(false, "Unsupported D type: "~T.stringof);
199 201
    }

@@ -9,7 +9,7 @@
Loading
9 9
import vibe.data.bson;
10 10
import std.uuid;
11 11
import std.datetime: SysTime, dur, TimeZone, UTC;
12 -
import std.bitmanip: bigEndianToNative;
12 +
import std.bitmanip: bigEndianToNative, BitArray;
13 13
import std.conv: to;
14 14
15 15
///
Files Coverage
src/dpq2 92.08%
integration_tests/integration_tests.d 100.00%
Project Totals (19 files) 92.11%
1179.17
TRAVIS_OS_NAME=linux
1178.17
TRAVIS_OS_NAME=linux
1181.17
TRAVIS_OS_NAME=linux
1180.17
TRAVIS_OS_NAME=linux
1182.17
TRAVIS_OS_NAME=linux

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading