16
16
module geod24.bitblob ;
17
17
18
18
static import std.ascii ;
19
- import std.algorithm ;
19
+ import std.algorithm.iteration : each, map ;
20
20
import std.range ;
21
21
import std.utf ;
22
22
@@ -61,6 +61,9 @@ public struct BitBlob (size_t Bits)
61
61
Bits % 8 == 0 ,
62
62
" Argument to BitBlob must be a multiple of 8" );
63
63
64
+ // / The width of this aggregate, in octets
65
+ public static immutable Width = Bits / 8 ;
66
+
64
67
// / Convenience enum
65
68
public enum StringBufferSize = (Width * 2 + 2 );
66
69
@@ -131,7 +134,15 @@ public struct BitBlob (size_t Bits)
131
134
assert (bin.length == Width);
132
135
this .data[] = bin[];
133
136
if (! isLE)
134
- this .data[].reverse;
137
+ {
138
+ foreach (cnt; 0 .. Width / 2 )
139
+ {
140
+ // Not sure the frontend is clever enough to avoid bounds checks
141
+ this .data[cnt] ^= this .data[$ - 1 - cnt];
142
+ this .data[$ - 1 - cnt] ^= this .data[cnt];
143
+ this .data[cnt] ^= this .data[$ - 1 - cnt];
144
+ }
145
+ }
135
146
}
136
147
137
148
/* **************************************************************************
@@ -150,12 +161,17 @@ public struct BitBlob (size_t Bits)
150
161
151
162
public this (scope const (char )[] hexstr)
152
163
{
153
- assert (hexstr.length == (Width * 2 )
154
- || hexstr.length == (Width * 2 ) + " 0x" .length);
164
+ enum ErrorMsg = " Wrong string size passed to ctor" ;
165
+ if (hexstr.length == (Width * 2 ) + " 0x" .length)
166
+ {
167
+ assert (hexstr[0 ] == ' 0' , ErrorMsg);
168
+ assert (hexstr[1 ] == ' x' || hexstr[1 ] == ' X' , ErrorMsg);
169
+ hexstr = hexstr[2 .. $];
170
+ }
171
+ else
172
+ assert (hexstr.length == (Width * 2 ), ErrorMsg);
155
173
156
174
auto range = hexstr.byChar.map! (std.ascii.toLower ! (char ));
157
- range.skipOver(" 0x" .byChar);
158
- // Each doesn't work
159
175
foreach (size_t idx, chunk; range.map! (fromHex).chunks(2 ).retro.enumerate)
160
176
this .data[idx] = cast (ubyte )((chunk[0 ] << 4 ) + chunk[1 ]);
161
177
}
@@ -176,9 +192,6 @@ public struct BitBlob (size_t Bits)
176
192
return BitBlob! (Bits)(str);
177
193
}
178
194
179
- // / The width of this aggregate, in octets
180
- public static immutable Width = Bits / 8 ;
181
-
182
195
// / Store the internal data
183
196
private ubyte [Width] data;
184
197
@@ -272,6 +285,16 @@ unittest
272
285
assert (statsBefore.usedSize == statsAfter.usedSize);
273
286
}
274
287
288
+ // / Test initialization from big endian
289
+ @safe unittest
290
+ {
291
+ import std.algorithm.mutation : reverse;
292
+ ubyte [32 ] genesis = GenesisBlockHash;
293
+ genesis[].reverse;
294
+ auto h = BitBlob! (256 )(genesis, false );
295
+ assert (h.toString() == GenesisBlockHashStr);
296
+ }
297
+
275
298
version (unittest )
276
299
{
277
300
private :
0 commit comments