1616module geod24.bitblob ;
1717
1818static import std.ascii ;
19- import std.algorithm ;
19+ import std.algorithm.iteration : each, map ;
2020import std.range ;
2121import std.utf ;
2222
@@ -61,6 +61,9 @@ public struct BitBlob (size_t Bits)
6161 Bits % 8 == 0 ,
6262 " Argument to BitBlob must be a multiple of 8" );
6363
64+ // / The width of this aggregate, in octets
65+ public static immutable Width = Bits / 8 ;
66+
6467 // / Convenience enum
6568 public enum StringBufferSize = (Width * 2 + 2 );
6669
@@ -131,7 +134,15 @@ public struct BitBlob (size_t Bits)
131134 assert (bin.length == Width);
132135 this .data[] = bin[];
133136 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+ }
135146 }
136147
137148 /* **************************************************************************
@@ -150,12 +161,17 @@ public struct BitBlob (size_t Bits)
150161
151162 public this (scope const (char )[] hexstr)
152163 {
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);
155173
156174 auto range = hexstr.byChar.map! (std.ascii.toLower ! (char ));
157- range.skipOver(" 0x" .byChar);
158- // Each doesn't work
159175 foreach (size_t idx, chunk; range.map! (fromHex).chunks(2 ).retro.enumerate)
160176 this .data[idx] = cast (ubyte )((chunk[0 ] << 4 ) + chunk[1 ]);
161177 }
@@ -176,9 +192,6 @@ public struct BitBlob (size_t Bits)
176192 return BitBlob! (Bits)(str);
177193 }
178194
179- // / The width of this aggregate, in octets
180- public static immutable Width = Bits / 8 ;
181-
182195 // / Store the internal data
183196 private ubyte [Width] data;
184197
@@ -272,6 +285,16 @@ unittest
272285 assert (statsBefore.usedSize == statsAfter.usedSize);
273286}
274287
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+
275298version (unittest )
276299{
277300private :
0 commit comments