1 // Written in the D programming language.
2 
3 /**
4 Bit-level manipulation facilities.
5 
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(DIVC quickindex,
8 $(BOOKTABLE,
9 $(TR $(TH Category) $(TH Functions))
10 $(TR $(TD Bit constructs) $(TD
11     $(LREF BitArray)
12     $(LREF bitfields)
13     $(LREF bitsSet)
14 ))
15 $(TR $(TD Endianness conversion) $(TD
16     $(LREF bigEndianToNative)
17     $(LREF littleEndianToNative)
18     $(LREF nativeToBigEndian)
19     $(LREF nativeToLittleEndian)
20     $(LREF swapEndian)
21 ))
22 $(TR $(TD Integral ranges) $(TD
23     $(LREF append)
24     $(LREF peek)
25     $(LREF read)
26     $(LREF write)
27 ))
28 $(TR $(TD Floating-Point manipulation) $(TD
29     $(LREF DoubleRep)
30     $(LREF FloatRep)
31 ))
32 $(TR $(TD Tagging) $(TD
33     $(LREF taggedClassRef)
34     $(LREF taggedPointer)
35 ))
36 ))
37 
38 Copyright: Copyright The D Language Foundation 2007 - 2011.
39 License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
40 Authors:   $(HTTP digitalmars.com, Walter Bright),
41            $(HTTP erdani.org, Andrei Alexandrescu),
42            $(HTTP jmdavisprog.com, Jonathan M Davis),
43            Alex Rønne Petersen,
44            Damian Ziemba,
45            Amaury SECHET
46 Source: $(PHOBOSSRC std/bitmanip.d)
47 */
48 /*
49          Copyright The D Language Foundation 2007 - 2012.
50 Distributed under the Boost Software License, Version 1.0.
51    (See accompanying file LICENSE_1_0.txt or copy at
52          http://www.boost.org/LICENSE_1_0.txt)
53 */
54 module std.bitmanip;
55 
56 import std.range.primitives;
57 public import std.system : Endian;
58 import std.traits;
59 
60 private string myToString(ulong n) pure @safe
61 {
62     import core.internal.string : UnsignedStringBuf, unsignedToTempString;
63     UnsignedStringBuf buf;
64     auto s = unsignedToTempString(n, buf);
65     // pure allows implicit cast to string
66     return s ~ (n > uint.max ? "UL" : "U");
67 }
68 
69 @safe pure unittest
70 {
71     assert(myToString(5) == "5U");
72     assert(myToString(uint.max) == "4294967295U");
73     assert(myToString(uint.max + 1UL) == "4294967296UL");
74 }
75 
76 
77 private template createAccessors(
78     string store, T, string name, size_t len, size_t offset)
79 {
80     static if (!name.length)
81     {
82         // No need to create any accessor
83         enum createAccessors = "";
84     }
85     else static if (len == 0)
86     {
87         // Fields of length 0 are always zero
88         enum createAccessors = "enum "~T.stringof~" "~name~" = 0;\n";
89     }
90     else
91     {
92         enum ulong maskAllElse = ((~0uL) >> (64 - len)) << offset;
93         enum TSize = 8 * T.sizeof;
94         enum SignShift = TSize - len;
95 
96         static if (T.min < 0)
97         {
98             enum long minVal = -(1uL << (len - 1));
99             enum ulong maxVal = (1uL << (len - 1)) - 1;
100             enum RightShiftOp = ">>=";
101         }
102         else
103         {
104             enum ulong minVal = 0;
105             enum ulong maxVal = (~0uL) >> (64 - len);
106             enum RightShiftOp = ">>>=";
107         }
108 
109         static if (is(T == bool))
110         {
111             enum createAccessors =
112             // getter
113                 "@property bool " ~ name ~ "() @safe pure nothrow @nogc const { return "
114                 ~"("~store~" & "~myToString(maskAllElse)~") != 0;}\n"
115             // setter
116                 ~"@property void " ~ name ~ "(bool v) @safe pure nothrow @nogc { "
117                 ~"if (v) "~store~" |= "~myToString(maskAllElse)~";"
118                 ~"else "~store~" &= cast(typeof("~store~"))(-1-cast(typeof("~store~"))"~myToString(maskAllElse)~");}\n";
119         }
120         else
121         {
122             // getter
123             enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const {"
124                 ~ "auto result = cast("~T.stringof~") (" ~ store ~ " >>" ~ myToString(offset) ~ ");"
125                 ~ "result <<= " ~ myToString(SignShift) ~ ";"
126                 ~ "result " ~ RightShiftOp ~ myToString(SignShift) ~ ";"
127                 ~ " return result;}\n"
128             // setter
129                 ~"@property void "~name~"("~T.stringof~" v) @safe pure nothrow @nogc { "
130                 ~"assert(v >= "~name~`_min, "Value is smaller than the minimum value of bitfield '`~name~`'"); `
131                 ~"assert(v <= "~name~`_max, "Value is greater than the maximum value of bitfield '`~name~`'"); `
132                 ~store~" = cast(typeof("~store~"))"
133                 ~" (("~store~" & (-1-cast(typeof("~store~"))"~myToString(maskAllElse)~"))"
134                 ~" | ((cast(typeof("~store~")) v << "~myToString(offset)~")"
135                 ~" & "~myToString(maskAllElse)~"));}\n"
136             // constants
137                 ~"enum "~T.stringof~" "~name~"_min = cast("~T.stringof~")"
138                 ~myToString(minVal)~"; "
139                 ~" enum "~T.stringof~" "~name~"_max = cast("~T.stringof~")"
140                 ~myToString(maxVal)~"; ";
141         }
142     }
143 }
144 
145 private template createStoreName(Ts...)
146 {
147     static if (Ts.length < 2)
148         enum createStoreName = "_bf";
149     else
150         enum createStoreName = "_" ~ Ts[1] ~ createStoreName!(Ts[3 .. $]);
151 }
152 
153 private template createStorageAndFields(Ts...)
154 {
155     enum Name = createStoreName!Ts;
156     enum Size = sizeOfBitField!Ts;
157     static if (Size == ubyte.sizeof * 8)
158         alias StoreType = ubyte;
159     else static if (Size == ushort.sizeof * 8)
160         alias StoreType = ushort;
161     else static if (Size == uint.sizeof * 8)
162         alias StoreType = uint;
163     else static if (Size == ulong.sizeof * 8)
164         alias StoreType = ulong;
165     else
166     {
167         import std.conv : to;
168         static assert(false, "Field widths must sum to 8, 16, 32, or 64, not " ~ to!string(Size));
169         alias StoreType = ulong; // just to avoid another error msg
170     }
171 
172     enum createStorageAndFields
173         = "private " ~ StoreType.stringof ~ " " ~ Name ~ ";"
174         ~ createFields!(Name, 0, Ts);
175 }
176 
177 private template createFields(string store, size_t offset, Ts...)
178 {
179     static if (Ts.length > 0)
180         enum createFields
181             = createAccessors!(store, Ts[0], Ts[1], Ts[2], offset)
182             ~ createFields!(store, offset + Ts[2], Ts[3 .. $]);
183     else
184         enum createFields = "";
185 }
186 
187 private ulong getBitsForAlign(ulong a)
188 {
189     ulong bits = 0;
190     while ((a & 0x01) == 0)
191     {
192         bits++;
193         a >>= 1;
194     }
195 
196     assert(a == 1, "alignment is not a power of 2");
197     return bits;
198 }
199 
200 private template createReferenceAccessor(string store, T, ulong bits, string name)
201 {
202     enum storage = "private void* " ~ store ~ "_ptr;\n";
203     enum storage_accessor = "@property ref size_t " ~ store ~ "() return @trusted pure nothrow @nogc const { "
204         ~ "return *cast(size_t*) &" ~ store ~ "_ptr;}\n"
205         ~ "@property void " ~ store ~ "(size_t v) @trusted pure nothrow @nogc { "
206         ~ "" ~ store ~ "_ptr = cast(void*) v;}\n";
207 
208     enum mask = (1UL << bits) - 1;
209     // getter
210     enum ref_accessor = "@property "~T.stringof~" "~name~"() @trusted pure nothrow @nogc const { auto result = "
211         ~ "("~store~" & "~myToString(~mask)~"); "
212         ~ "return cast("~T.stringof~") cast(void*) result;}\n"
213     // setter
214         ~"@property void "~name~"("~T.stringof~" v) @trusted pure nothrow @nogc { "
215         ~"assert(((cast(typeof("~store~")) cast(void*) v) & "~myToString(mask)
216         ~`) == 0, "Value not properly aligned for '`~name~`'"); `
217         ~store~" = cast(typeof("~store~"))"
218         ~" (("~store~" & (cast(typeof("~store~")) "~myToString(mask)~"))"
219         ~" | ((cast(typeof("~store~")) cast(void*) v) & (cast(typeof("~store~")) "~myToString(~mask)~")));}\n";
220 
221     enum createReferenceAccessor = storage ~ storage_accessor ~ ref_accessor;
222 }
223 
224 private template sizeOfBitField(T...)
225 {
226     static if (T.length < 2)
227         enum sizeOfBitField = 0;
228     else
229         enum sizeOfBitField = T[2] + sizeOfBitField!(T[3 .. $]);
230 }
231 
232 private template createTaggedReference(T, ulong a, string name, Ts...)
233 {
234     static assert(
235         sizeOfBitField!Ts <= getBitsForAlign(a),
236         "Fields must fit in the bits know to be zero because of alignment."
237     );
238     enum StoreName = createStoreName!(T, name, 0, Ts);
239     enum createTaggedReference
240         = createReferenceAccessor!(StoreName, T, sizeOfBitField!Ts, name)
241         ~ createFields!(StoreName, 0, Ts, size_t, "", T.sizeof * 8 - sizeOfBitField!Ts);
242 }
243 
244 /**
245 Allows creating `bitfields` inside `structs`, `classes` and `unions`.
246 
247 A `bitfield` consists of one or more entries with a fixed number of
248 bits reserved for each of the entries. The types of the entries can
249 be `bool`s, integral types or enumerated types, arbitrarily mixed.
250 The most efficient type to store in `bitfields` is `bool`, followed
251 by unsigned types, followed by signed types.
252 
253 Each non-`bool` entry of the `bitfield` will be represented by the
254 number of bits specified by the user. The minimum and the maximum
255 numbers that represent this domain can be queried by using the name
256 of the variable followed by `_min` or `_max`.
257 
258 Limitation: The number of bits in a `bitfield` is limited to 8, 16,
259 32 or 64. If padding is needed, an entry should be explicitly
260 allocated with an empty name.
261 
262 Implementation_details: `Bitfields` are internally stored in an
263 `ubyte`, `ushort`, `uint` or `ulong` depending on the number of bits
264 used. The bits are filled in the order given by the parameters,
265 starting with the lowest significant bit. The name of the (private)
266 variable used for saving the `bitfield` is created by a prefix `_bf`
267 and concatenating all of the variable names, each preceded by an
268 underscore.
269 
270 Params: T = A list of template parameters divided into chunks of 3
271             items. Each chunk consists (in this order) of a type, a
272             name and a number. Together they define an entry
273             of the `bitfield`: a variable of the given type and name,
274             which can hold as many bits as the number denotes.
275 
276 Returns: A string that can be used in a `mixin` to add the `bitfield`.
277 
278 See_Also: $(REF BitFlags, std,typecons)
279 */
280 string bitfields(T...)()
281 {
282     import std.conv : to;
283 
284     static assert(T.length % 3 == 0,
285                   "Wrong number of arguments (" ~ to!string(T.length) ~ "): Must be a multiple of 3");
286 
287     static foreach (i, ARG; T)
288     {
289         static if (i % 3 == 0)
290             static assert(is (typeof({ARG tmp = cast (ARG)0; if (ARG.min < 0) {} }())),
291                           "Integral type or `bool` expected, found " ~ ARG.stringof);
292 
293         // would be nice to check for valid variable names too
294         static if (i % 3 == 1)
295             static assert(is (typeof(ARG) : string),
296                           "Variable name expected, found " ~ ARG.stringof);
297 
298         static if (i % 3 == 2)
299         {
300             static assert(is (typeof({ulong tmp = ARG;}())),
301                           "Integral value expected, found " ~ ARG.stringof);
302 
303             static if (T[i-1] != "")
304             {
305                 static assert(!is (T[i-2] : bool) || ARG <= 1,
306                               "Type `bool` is only allowed for single-bit fields");
307 
308                 static assert(ARG >= 0 && ARG <= T[i-2].sizeof * 8,
309                               "Wrong size of bitfield: " ~ ARG.stringof);
310             }
311         }
312     }
313 
314     return createStorageAndFields!T;
315 }
316 
317 /**
318 Create a `bitfield` pack of eight bits, which fit in
319 one `ubyte`. The `bitfields` are allocated starting from the
320 least significant bit, i.e. `x` occupies the two least significant bits
321 of the `bitfields` storage.
322 */
323 @safe unittest
324 {
325     struct A
326     {
327         int a;
328         mixin(bitfields!(
329             uint, "x",    2,
330             int,  "y",    3,
331             uint, "z",    2,
332             bool, "flag", 1));
333     }
334 
335     A obj;
336     obj.x = 2;
337     obj.z = obj.x;
338 
339     assert(obj.x == 2);
340     assert(obj.y == 0);
341     assert(obj.z == 2);
342     assert(obj.flag == false);
343 }
344 
345 /**
346 The sum of all bit lengths in one `bitfield` instantiation
347 must be exactly 8, 16, 32, or 64. If padding is needed, just allocate
348 one bitfield with an empty name.
349 */
350 @safe unittest
351 {
352     struct A
353     {
354         mixin(bitfields!(
355             bool, "flag1",    1,
356             bool, "flag2",    1,
357             uint, "",         6));
358     }
359 
360     A a;
361     assert(a.flag1 == 0);
362     a.flag1 = 1;
363     assert(a.flag1 == 1);
364     a.flag1 = 0;
365     assert(a.flag1 == 0);
366 }
367 
368 /// enums can be used too
369 @safe unittest
370 {
371     enum ABC { A, B, C }
372     struct EnumTest
373     {
374         mixin(bitfields!(
375                   ABC, "x", 2,
376                   bool, "y", 1,
377                   ubyte, "z", 5));
378     }
379 }
380 
381 @safe pure nothrow @nogc
382 unittest
383 {
384     // Degenerate bitfields tests mixed with range tests
385     // https://issues.dlang.org/show_bug.cgi?id=8474
386     // https://issues.dlang.org/show_bug.cgi?id=11160
387     struct Test1
388     {
389         mixin(bitfields!(uint, "a", 32,
390                         uint, "b", 4,
391                         uint, "c", 4,
392                         uint, "d", 8,
393                         uint, "e", 16,));
394 
395         static assert(Test1.b_min == 0);
396         static assert(Test1.b_max == 15);
397     }
398 
399     struct Test2
400     {
401         mixin(bitfields!(bool, "a", 0,
402                         ulong, "b", 64));
403 
404         static assert(Test2.b_min == ulong.min);
405         static assert(Test2.b_max == ulong.max);
406     }
407 
408     struct Test1b
409     {
410         mixin(bitfields!(bool, "a", 0,
411                         int, "b", 8));
412     }
413 
414     struct Test2b
415     {
416         mixin(bitfields!(int, "a", 32,
417                         int, "b", 4,
418                         int, "c", 4,
419                         int, "d", 8,
420                         int, "e", 16,));
421 
422         static assert(Test2b.b_min == -8);
423         static assert(Test2b.b_max == 7);
424     }
425 
426     struct Test3b
427     {
428         mixin(bitfields!(bool, "a", 0,
429                         long, "b", 64));
430 
431         static assert(Test3b.b_min == long.min);
432         static assert(Test3b.b_max == long.max);
433     }
434 
435     struct Test4b
436     {
437         mixin(bitfields!(long, "a", 32,
438                         int, "b", 32));
439     }
440 
441     // Sign extension tests
442     Test2b t2b;
443     Test4b t4b;
444     t2b.b = -5; assert(t2b.b == -5);
445     t2b.d = -5; assert(t2b.d == -5);
446     t2b.e = -5; assert(t2b.e == -5);
447     t4b.a = -5; assert(t4b.a == -5L);
448 }
449 
450 // https://issues.dlang.org/show_bug.cgi?id=6686
451 @safe unittest
452 {
453     union  S {
454         ulong bits = ulong.max;
455         mixin (bitfields!(
456             ulong, "back",  31,
457             ulong, "front", 33)
458         );
459     }
460     S num;
461 
462     num.bits = ulong.max;
463     num.back = 1;
464     assert(num.bits == 0xFFFF_FFFF_8000_0001uL);
465 }
466 
467 // https://issues.dlang.org/show_bug.cgi?id=5942
468 @safe unittest
469 {
470     struct S
471     {
472         mixin(bitfields!(
473             int, "a" , 32,
474             int, "b" , 32
475         ));
476     }
477 
478     S data;
479     data.b = 42;
480     data.a = 1;
481     assert(data.b == 42);
482 }
483 
484 @safe unittest
485 {
486     struct Test
487     {
488         mixin(bitfields!(bool, "a", 1,
489                          uint, "b", 3,
490                          short, "c", 4));
491     }
492 
493     @safe void test() pure nothrow
494     {
495         Test t;
496 
497         t.a = true;
498         t.b = 5;
499         t.c = 2;
500 
501         assert(t.a);
502         assert(t.b == 5);
503         assert(t.c == 2);
504     }
505 
506     test();
507 }
508 
509 @safe unittest
510 {
511     {
512         static struct Integrals {
513             bool checkExpectations(bool eb, int ei, short es) { return b == eb && i == ei && s == es; }
514 
515             mixin(bitfields!(
516                       bool, "b", 1,
517                       uint, "i", 3,
518                       short, "s", 4));
519         }
520         Integrals i;
521         assert(i.checkExpectations(false, 0, 0));
522         i.b = true;
523         assert(i.checkExpectations(true, 0, 0));
524         i.i = 7;
525         assert(i.checkExpectations(true, 7, 0));
526         i.s = -8;
527         assert(i.checkExpectations(true, 7, -8));
528         i.s = 7;
529         assert(i.checkExpectations(true, 7, 7));
530     }
531 
532     //https://issues.dlang.org/show_bug.cgi?id=8876
533     {
534         struct MoreIntegrals {
535             bool checkExpectations(uint eu, ushort es, uint ei) { return u == eu && s == es && i == ei; }
536 
537             mixin(bitfields!(
538                   uint, "u", 24,
539                   short, "s", 16,
540                   int, "i", 24));
541         }
542 
543         MoreIntegrals i;
544         assert(i.checkExpectations(0, 0, 0));
545         i.s = 20;
546         assert(i.checkExpectations(0, 20, 0));
547         i.i = 72;
548         assert(i.checkExpectations(0, 20, 72));
549         i.u = 8;
550         assert(i.checkExpectations(8, 20, 72));
551         i.s = 7;
552         assert(i.checkExpectations(8, 7, 72));
553     }
554 
555     enum A { True, False }
556     enum B { One, Two, Three, Four }
557     static struct Enums {
558         bool checkExpectations(A ea, B eb) { return a == ea && b == eb; }
559 
560         mixin(bitfields!(
561                   A, "a", 1,
562                   B, "b", 2,
563                   uint, "", 5));
564     }
565     Enums e;
566     assert(e.checkExpectations(A.True, B.One));
567     e.a = A.False;
568     assert(e.checkExpectations(A.False, B.One));
569     e.b = B.Three;
570     assert(e.checkExpectations(A.False, B.Three));
571 
572     static struct SingleMember {
573         bool checkExpectations(bool eb) { return b == eb; }
574 
575         mixin(bitfields!(
576                   bool, "b", 1,
577                   uint, "", 7));
578     }
579     SingleMember f;
580     assert(f.checkExpectations(false));
581     f.b = true;
582     assert(f.checkExpectations(true));
583 }
584 
585 // https://issues.dlang.org/show_bug.cgi?id=12477
586 @system unittest
587 {
588     import core.exception : AssertError;
589     import std.algorithm.searching : canFind;
590 
591     static struct S
592     {
593         mixin(bitfields!(
594             uint, "a", 6,
595             int, "b", 2));
596     }
597 
598     S s;
599 
600     try { s.a = uint.max; assert(0); }
601     catch (AssertError ae)
602     { assert(ae.msg.canFind("Value is greater than the maximum value of bitfield 'a'"), ae.msg); }
603 
604     try { s.b = int.min;  assert(0); }
605     catch (AssertError ae)
606     { assert(ae.msg.canFind("Value is smaller than the minimum value of bitfield 'b'"), ae.msg); }
607 }
608 
609 // https://issues.dlang.org/show_bug.cgi?id=15305
610 @safe unittest
611 {
612     struct S {
613             mixin(bitfields!(
614                     bool, "alice", 1,
615                     ulong, "bob", 63,
616             ));
617     }
618 
619     S s;
620     s.bob = long.max - 1;
621     s.alice = false;
622     assert(s.bob == long.max - 1);
623 }
624 
625 // https://issues.dlang.org/show_bug.cgi?id=21634
626 @safe unittest
627 {
628     struct A
629     {
630         mixin(bitfields!(int, "", 1,
631                          int, "gshared", 7));
632     }
633 }
634 
635 // https://issues.dlang.org/show_bug.cgi?id=21725
636 @safe unittest
637 {
638     struct S
639     {
640         mixin(bitfields!(
641             uint, q{foo}, 4,
642             uint, null, 4,
643         ));
644     }
645 }
646 
647 /**
648 This string mixin generator allows one to create tagged pointers inside $(D_PARAM struct)s and $(D_PARAM class)es.
649 
650 A tagged pointer uses the bits known to be zero in a normal pointer or class reference to store extra information.
651 For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
652 One can store a 2-bit integer there.
653 
654 The example above creates a tagged pointer in the struct A. The pointer is of type
655 `uint*` as specified by the first argument, and is named x, as specified by the second
656 argument.
657 
658 Following arguments works the same way as `bitfield`'s. The bitfield must fit into the
659 bits known to be zero because of the pointer alignment.
660 */
661 
662 template taggedPointer(T : T*, string name, Ts...) {
663     enum taggedPointer = createTaggedReference!(T*, T.alignof, name, Ts);
664 }
665 
666 ///
667 @safe unittest
668 {
669     struct A
670     {
671         int a;
672         mixin(taggedPointer!(
673             uint*, "x",
674             bool, "b1", 1,
675             bool, "b2", 1));
676     }
677     A obj;
678     obj.x = new uint;
679     obj.b1 = true;
680     obj.b2 = false;
681 }
682 
683 @system unittest
684 {
685     struct Test5
686     {
687         mixin(taggedPointer!(
688             int*, "a",
689             uint, "b", 2));
690     }
691 
692     Test5 t5;
693     t5.a = null;
694     t5.b = 3;
695     assert(t5.a is null);
696     assert(t5.b == 3);
697 
698     int myint = 42;
699     t5.a = &myint;
700     assert(t5.a is &myint);
701     assert(t5.b == 3);
702 }
703 
704 /**
705 This string mixin generator allows one to create tagged class reference inside $(D_PARAM struct)s and $(D_PARAM class)es.
706 
707 A tagged class reference uses the bits known to be zero in a normal class reference to store extra information.
708 For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
709 One can store a 2-bit integer there.
710 
711 The example above creates a tagged reference to an Object in the struct A. This expects the same parameters
712 as `taggedPointer`, except the first argument which must be a class type instead of a pointer type.
713 */
714 
715 template taggedClassRef(T, string name, Ts...)
716 if (is(T == class))
717 {
718     enum taggedClassRef = createTaggedReference!(T, 8, name, Ts);
719 }
720 
721 ///
722 @safe unittest
723 {
724     struct A
725     {
726         int a;
727         mixin(taggedClassRef!(
728             Object, "o",
729             uint, "i", 2));
730     }
731     A obj;
732     obj.o = new Object();
733     obj.i = 3;
734 }
735 
736 @system unittest
737 {
738     struct Test6
739     {
740         mixin(taggedClassRef!(
741             Object, "o",
742             bool, "b", 1));
743     }
744 
745     Test6 t6;
746     t6.o = null;
747     t6.b = false;
748     assert(t6.o is null);
749     assert(t6.b == false);
750 
751     auto o = new Object();
752     t6.o = o;
753     t6.b = true;
754     assert(t6.o is o);
755     assert(t6.b == true);
756 }
757 
758 @safe unittest
759 {
760     static assert(!__traits(compiles,
761         taggedPointer!(
762             int*, "a",
763             uint, "b", 3)));
764 
765     static assert(!__traits(compiles,
766         taggedClassRef!(
767             Object, "a",
768             uint, "b", 4)));
769 
770     struct S {
771         mixin(taggedClassRef!(
772             Object, "a",
773             bool, "b", 1));
774     }
775 
776     const S s;
777     void bar(S s) {}
778 
779     static assert(!__traits(compiles, bar(s)));
780 }
781 
782 private struct FloatingPointRepresentation(T)
783 {
784     static if (is(T == float))
785     {
786         enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
787         alias FractionType = uint;
788         alias ExponentType = ubyte;
789     }
790     else
791     {
792         enum uint bias = 1023, fractionBits = 52, exponentBits = 11, signBits = 1;
793         alias FractionType = ulong;
794         alias ExponentType = ushort;
795     }
796 
797     union
798     {
799         T value;
800         mixin(bitfields!(
801                   FractionType, "fraction", fractionBits,
802                   ExponentType, "exponent", exponentBits,
803                   bool,  "sign",     signBits));
804     }
805 }
806 
807 /**
808    Allows manipulating the fraction, exponent, and sign parts of a
809    `float` separately. The definition is:
810 
811 ----
812 struct FloatRep
813 {
814     union
815     {
816         float value;
817         mixin(bitfields!(
818                   uint,  "fraction", 23,
819                   ubyte, "exponent",  8,
820                   bool,  "sign",      1));
821     }
822     enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
823 }
824 ----
825 */
826 alias FloatRep = FloatingPointRepresentation!float;
827 
828 ///
829 @safe unittest
830 {
831     FloatRep rep = {value: 0};
832     assert(rep.fraction == 0);
833     assert(rep.exponent == 0);
834     assert(!rep.sign);
835 
836     rep.value = 42;
837     assert(rep.fraction == 2621440);
838     assert(rep.exponent == 132);
839     assert(!rep.sign);
840 
841     rep.value = 10;
842     assert(rep.fraction == 2097152);
843     assert(rep.exponent == 130);
844 }
845 
846 ///
847 @safe unittest
848 {
849     FloatRep rep = {value: 1};
850     assert(rep.fraction == 0);
851     assert(rep.exponent == 127);
852     assert(!rep.sign);
853 
854     rep.exponent = 126;
855     assert(rep.value == 0.5);
856 
857     rep.exponent = 130;
858     assert(rep.value == 8);
859 }
860 
861 ///
862 @safe unittest
863 {
864     FloatRep rep = {value: 1};
865     rep.value = -0.5;
866     assert(rep.fraction == 0);
867     assert(rep.exponent == 126);
868     assert(rep.sign);
869 
870     rep.value = -1. / 3;
871     assert(rep.fraction == 2796203);
872     assert(rep.exponent == 125);
873     assert(rep.sign);
874 }
875 
876 /**
877    Allows manipulating the fraction, exponent, and sign parts of a
878    `double` separately. The definition is:
879 
880 ----
881 struct DoubleRep
882 {
883     union
884     {
885         double value;
886         mixin(bitfields!(
887                   ulong,   "fraction", 52,
888                   ushort,  "exponent", 11,
889                   bool,    "sign",      1));
890     }
891     enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11;
892 }
893 ----
894 */
895 alias DoubleRep = FloatingPointRepresentation!double;
896 
897 ///
898 @safe unittest
899 {
900     DoubleRep rep = {value: 0};
901     assert(rep.fraction == 0);
902     assert(rep.exponent == 0);
903     assert(!rep.sign);
904 
905     rep.value = 42;
906     assert(rep.fraction == 1407374883553280);
907     assert(rep.exponent == 1028);
908     assert(!rep.sign);
909 
910     rep.value = 10;
911     assert(rep.fraction == 1125899906842624);
912     assert(rep.exponent == 1026);
913 }
914 
915 ///
916 @safe unittest
917 {
918     DoubleRep rep = {value: 1};
919     assert(rep.fraction == 0);
920     assert(rep.exponent == 1023);
921     assert(!rep.sign);
922 
923     rep.exponent = 1022;
924     assert(rep.value == 0.5);
925 
926     rep.exponent = 1026;
927     assert(rep.value == 8);
928 }
929 
930 ///
931 @safe unittest
932 {
933     DoubleRep rep = {value: 1};
934     rep.value = -0.5;
935     assert(rep.fraction == 0);
936     assert(rep.exponent == 1022);
937     assert(rep.sign);
938 
939     rep.value = -1. / 3;
940     assert(rep.fraction == 1501199875790165);
941     assert(rep.exponent == 1021);
942     assert(rep.sign);
943 }
944 
945 /// Reading
946 @safe unittest
947 {
948     DoubleRep x;
949     x.value = 1.0;
950     assert(x.fraction == 0 && x.exponent == 1023 && !x.sign);
951     x.value = -0.5;
952     assert(x.fraction == 0 && x.exponent == 1022 && x.sign);
953     x.value = 0.5;
954     assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
955 }
956 
957 /// Writing
958 @safe unittest
959 {
960     DoubleRep x;
961     x.fraction = 1125899906842624;
962     x.exponent = 1025;
963     x.sign = true;
964     assert(x.value == -5.0);
965 }
966 
967 /**
968 A dynamic array of bits. Each bit in a `BitArray` can be manipulated individually
969 or by the standard bitwise operators `&`, `|`, `^`, `~`, `>>`, `<<` and also by
970 other effective member functions; most of them work relative to the `BitArray`'s
971 dimension (see $(LREF dim)), instead of its $(LREF length).
972 */
973 struct BitArray
974 {
975 private:
976 
977     import core.bitop : btc, bts, btr, bsf, bt;
978     import std.format.spec : FormatSpec;
979 
980     size_t _len;
981     size_t* _ptr;
982     enum bitsPerSizeT = size_t.sizeof * 8;
983 
984     @property size_t fullWords() const scope @safe @nogc pure nothrow
985     {
986         return _len / bitsPerSizeT;
987     }
988     // Number of bits after the last full word
989     @property size_t endBits() const scope @safe @nogc pure nothrow
990     {
991         return _len % bitsPerSizeT;
992     }
993     // Bit mask to extract the bits after the last full word
994     @property size_t endMask() const scope @safe @nogc pure nothrow
995     {
996         return (size_t(1) << endBits) - 1;
997     }
998     static size_t lenToDim(size_t len) @nogc pure nothrow @safe
999     {
1000         return (len + (bitsPerSizeT-1)) / bitsPerSizeT;
1001     }
1002 
1003 public:
1004     /**
1005     Creates a `BitArray` from a `bool` array, such that `bool` values read
1006     from left to right correspond to subsequent bits in the `BitArray`.
1007 
1008     Params: ba = Source array of `bool` values.
1009     */
1010     this(in bool[] ba) nothrow pure
1011     {
1012         length = ba.length;
1013         foreach (i, b; ba)
1014         {
1015             this[i] = b;
1016         }
1017     }
1018 
1019     ///
1020     @system unittest
1021     {
1022         import std.algorithm.comparison : equal;
1023 
1024         bool[] input = [true, false, false, true, true];
1025         auto a = BitArray(input);
1026         assert(a.length == 5);
1027         assert(a.bitsSet.equal([0, 3, 4]));
1028 
1029         // This also works because an implicit cast to bool[] occurs for this array.
1030         auto b = BitArray([0, 0, 1]);
1031         assert(b.length == 3);
1032         assert(b.bitsSet.equal([2]));
1033     }
1034 
1035     ///
1036     @system unittest
1037     {
1038         import std.algorithm.comparison : equal;
1039         import std.array : array;
1040         import std.range : iota, repeat;
1041 
1042         BitArray a = true.repeat(70).array;
1043         assert(a.length == 70);
1044         assert(a.bitsSet.equal(iota(0, 70)));
1045     }
1046 
1047     /**
1048     Creates a `BitArray` from the raw contents of the source array. The
1049     source array is not copied but simply acts as the underlying array
1050     of bits, which stores data as `size_t` units.
1051 
1052     That means a particular care should be taken when passing an array
1053     of a type different than `size_t`, firstly because its length should
1054     be a multiple of `size_t.sizeof`, and secondly because how the bits
1055     are mapped:
1056     ---
1057     size_t[] source = [1, 2, 3, 3424234, 724398, 230947, 389492];
1058     enum sbits = size_t.sizeof * 8;
1059     auto ba = BitArray(source, source.length * sbits);
1060     foreach (n; 0 .. source.length * sbits)
1061     {
1062         auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits)));
1063         assert(ba[n] == nth_bit);
1064     }
1065     ---
1066     The least significant bit in any `size_t` unit is the starting bit of this
1067     unit, and the most significant bit is the last bit of this unit. Therefore,
1068     passing e.g. an array of `int`s may result in a different `BitArray`
1069     depending on the processor's endianness.
1070 
1071     This constructor is the inverse of $(LREF opCast).
1072 
1073     Params:
1074         v = Source array. `v.length` must be a multple of `size_t.sizeof`.
1075         numbits = Number of bits to be mapped from the source array, i.e.
1076                   length of the created `BitArray`.
1077     */
1078     this(void[] v, size_t numbits) @nogc nothrow pure
1079     in
1080     {
1081         assert(numbits <= v.length * 8,
1082                 "numbits must be less than or equal to v.length * 8");
1083         assert(v.length % size_t.sizeof == 0,
1084                 "v.length must be a multiple of the size of size_t");
1085     }
1086     do
1087     {
1088         _ptr = cast(size_t*) v.ptr;
1089         _len = numbits;
1090     }
1091 
1092     ///
1093     @system unittest
1094     {
1095         import std.algorithm.comparison : equal;
1096 
1097         auto a = BitArray([1, 0, 0, 1, 1]);
1098 
1099         // Inverse of the cast.
1100         auto v = cast(void[]) a;
1101         auto b = BitArray(v, a.length);
1102 
1103         assert(b.length == 5);
1104         assert(b.bitsSet.equal([0, 3, 4]));
1105 
1106         // a and b share the underlying data.
1107         a[0] = 0;
1108         assert(b[0] == 0);
1109         assert(a == b);
1110     }
1111 
1112     ///
1113     @system unittest
1114     {
1115         import std.algorithm.comparison : equal;
1116 
1117         size_t[] source = [0b1100, 0b0011];
1118         enum sbits = size_t.sizeof * 8;
1119         auto ba = BitArray(source, source.length * sbits);
1120         // The least significant bit in each unit is this unit's starting bit.
1121         assert(ba.bitsSet.equal([2, 3, sbits, sbits + 1]));
1122     }
1123 
1124     ///
1125     @system unittest
1126     {
1127         // Example from the doc for this constructor.
1128         static immutable size_t[] sourceData = [1, 0b101, 3, 3424234, 724398, 230947, 389492];
1129         size_t[] source = sourceData.dup;
1130         enum sbits = size_t.sizeof * 8;
1131         auto ba = BitArray(source, source.length * sbits);
1132         foreach (n; 0 .. source.length * sbits)
1133         {
1134             auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits)));
1135             assert(ba[n] == nth_bit);
1136         }
1137 
1138         // Example of mapping only part of the array.
1139         import std.algorithm.comparison : equal;
1140 
1141         auto bc = BitArray(source, sbits + 1);
1142         assert(bc.bitsSet.equal([0, sbits]));
1143         // Source array has not been modified.
1144         assert(source == sourceData);
1145     }
1146 
1147     // Deliberately undocumented: raw initialization of bit array.
1148     this(size_t len, size_t* ptr) @nogc nothrow pure
1149     {
1150         _len = len;
1151         _ptr = ptr;
1152     }
1153 
1154     /**
1155     Returns: Dimension i.e. the number of native words backing this `BitArray`.
1156 
1157     Technically, this is the length of the underlying array storing bits, which
1158     is equal to `ceil(length / (size_t.sizeof * 8))`, as bits are packed into
1159     `size_t` units.
1160     */
1161     @property size_t dim() const @nogc nothrow pure @safe
1162     {
1163         return lenToDim(_len);
1164     }
1165 
1166     /**
1167     Returns: Number of bits in the `BitArray`.
1168     */
1169     @property size_t length() const @nogc nothrow pure @safe
1170     {
1171         return _len;
1172     }
1173 
1174     /**********************************************
1175      * Sets the amount of bits in the `BitArray`.
1176      * $(RED Warning: increasing length may overwrite bits in
1177      * the final word of the current underlying data regardless
1178      * of whether it is shared between BitArray objects. i.e. D
1179      * dynamic array extension semantics are not followed.)
1180      */
1181     @property size_t length(size_t newlen) pure nothrow @system
1182     {
1183         if (newlen != _len)
1184         {
1185             size_t olddim = dim;
1186             immutable newdim = lenToDim(newlen);
1187 
1188             if (newdim != olddim)
1189             {
1190                 // Create a fake array so we can use D's realloc machinery
1191                 auto b = _ptr[0 .. olddim];
1192                 b.length = newdim;                // realloc
1193                 _ptr = b.ptr;
1194             }
1195 
1196             auto oldlen = _len;
1197             _len = newlen;
1198             if (oldlen < newlen)
1199             {
1200                 auto end = ((oldlen / bitsPerSizeT) + 1) * bitsPerSizeT;
1201                 if (end > newlen)
1202                     end = newlen;
1203                 this[oldlen .. end] = 0;
1204             }
1205         }
1206         return _len;
1207     }
1208 
1209     // https://issues.dlang.org/show_bug.cgi?id=20240
1210     @system unittest
1211     {
1212         BitArray ba;
1213 
1214         ba.length = 1;
1215         ba[0] = 1;
1216         ba.length = 0;
1217         ba.length = 1;
1218         assert(ba[0] == 0); // OK
1219 
1220         ba.length = 2;
1221         ba[1] = 1;
1222         ba.length = 1;
1223         ba.length = 2;
1224         assert(ba[1] == 0); // Fail
1225     }
1226 
1227     /**********************************************
1228      * Gets the `i`'th bit in the `BitArray`.
1229      */
1230     bool opIndex(size_t i) const @nogc pure nothrow
1231     in
1232     {
1233         assert(i < _len, "i must be less than the length");
1234     }
1235     do
1236     {
1237         return cast(bool) bt(_ptr, i);
1238     }
1239 
1240     ///
1241     @system unittest
1242     {
1243         static void fun(const BitArray arr)
1244         {
1245             auto x = arr[0];
1246             assert(x == 1);
1247         }
1248         BitArray a;
1249         a.length = 3;
1250         a[0] = 1;
1251         fun(a);
1252     }
1253 
1254     /**********************************************
1255      * Sets the `i`'th bit in the `BitArray`.
1256      */
1257     bool opIndexAssign(bool b, size_t i) @nogc pure nothrow
1258     in
1259     {
1260         assert(i < _len, "i must be less than the length");
1261     }
1262     do
1263     {
1264         if (b)
1265             bts(_ptr, i);
1266         else
1267             btr(_ptr, i);
1268         return b;
1269     }
1270 
1271     /**
1272       Sets all the values in the `BitArray` to the
1273       value specified by `val`.
1274      */
1275     void opSliceAssign(bool val) @nogc pure nothrow
1276     {
1277         _ptr[0 .. fullWords] = val ? ~size_t(0) : 0;
1278         if (endBits)
1279         {
1280             if (val)
1281                 _ptr[fullWords] |= endMask;
1282             else
1283                 _ptr[fullWords] &= ~endMask;
1284         }
1285     }
1286 
1287     ///
1288     @system pure nothrow unittest
1289     {
1290         import std.algorithm.comparison : equal;
1291 
1292         auto b = BitArray([1, 0, 1, 0, 1, 1]);
1293 
1294         b[] = true;
1295         // all bits are set
1296         assert(b.bitsSet.equal([0, 1, 2, 3, 4, 5]));
1297 
1298         b[] = false;
1299         // none of the bits are set
1300         assert(b.bitsSet.empty);
1301     }
1302 
1303     /**
1304       Sets the bits of a slice of `BitArray` starting
1305       at index `start` and ends at index ($D end - 1)
1306       with the values specified by `val`.
1307      */
1308     void opSliceAssign(bool val, size_t start, size_t end) @nogc pure nothrow
1309     in
1310     {
1311         assert(start <= end, "start must be less or equal to end");
1312         assert(end <= length, "end must be less or equal to the length");
1313     }
1314     do
1315     {
1316         size_t startBlock = start / bitsPerSizeT;
1317         size_t endBlock = end / bitsPerSizeT;
1318         size_t startOffset = start % bitsPerSizeT;
1319         size_t endOffset = end % bitsPerSizeT;
1320 
1321         if (startBlock == endBlock)
1322         {
1323             size_t startBlockMask = ~((size_t(1) << startOffset) - 1);
1324             size_t endBlockMask = (size_t(1) << endOffset) - 1;
1325             size_t joinMask = startBlockMask & endBlockMask;
1326             if (val)
1327                 _ptr[startBlock] |= joinMask;
1328             else
1329                 _ptr[startBlock] &= ~joinMask;
1330             return;
1331         }
1332 
1333         if (startOffset != 0)
1334         {
1335             size_t startBlockMask = ~((size_t(1) << startOffset) - 1);
1336             if (val)
1337                 _ptr[startBlock] |= startBlockMask;
1338             else
1339                 _ptr[startBlock] &= ~startBlockMask;
1340             ++startBlock;
1341         }
1342         if (endOffset != 0)
1343         {
1344             size_t endBlockMask = (size_t(1) << endOffset) - 1;
1345             if (val)
1346                 _ptr[endBlock] |= endBlockMask;
1347             else
1348                 _ptr[endBlock] &= ~endBlockMask;
1349         }
1350         _ptr[startBlock .. endBlock] = size_t(0) - size_t(val);
1351     }
1352 
1353     ///
1354     @system pure nothrow unittest
1355     {
1356         import std.algorithm.comparison : equal;
1357         import std.range : iota;
1358         import std.stdio;
1359 
1360         auto b = BitArray([1, 0, 0, 0, 1, 1, 0]);
1361         b[1 .. 3] = true;
1362         assert(b.bitsSet.equal([0, 1, 2, 4, 5]));
1363 
1364         bool[72] bitArray;
1365         auto b1 = BitArray(bitArray);
1366         b1[63 .. 67] = true;
1367         assert(b1.bitsSet.equal([63, 64, 65, 66]));
1368         b1[63 .. 67] = false;
1369         assert(b1.bitsSet.empty);
1370         b1[0 .. 64] = true;
1371         assert(b1.bitsSet.equal(iota(0, 64)));
1372         b1[0 .. 64] = false;
1373         assert(b1.bitsSet.empty);
1374 
1375         bool[256] bitArray2;
1376         auto b2 = BitArray(bitArray2);
1377         b2[3 .. 245] = true;
1378         assert(b2.bitsSet.equal(iota(3, 245)));
1379         b2[3 .. 245] = false;
1380         assert(b2.bitsSet.empty);
1381     }
1382 
1383     /**
1384       Flips all the bits in the `BitArray`
1385      */
1386     void flip() @nogc pure nothrow
1387     {
1388         foreach (i; 0 .. fullWords)
1389             _ptr[i] = ~_ptr[i];
1390 
1391         if (endBits)
1392             _ptr[fullWords] = (~_ptr[fullWords]) & endMask;
1393     }
1394 
1395     ///
1396     @system pure nothrow unittest
1397     {
1398         import std.algorithm.comparison : equal;
1399         import std.range : iota;
1400 
1401         // positions 0, 2, 4 are set
1402         auto b = BitArray([1, 0, 1, 0, 1, 0]);
1403         b.flip();
1404         // after flipping, positions 1, 3, 5 are set
1405         assert(b.bitsSet.equal([1, 3, 5]));
1406 
1407         bool[270] bits;
1408         auto b1 = BitArray(bits);
1409         b1.flip();
1410         assert(b1.bitsSet.equal(iota(0, 270)));
1411     }
1412 
1413     /**
1414       Flips a single bit, specified by `pos`
1415      */
1416     void flip(size_t pos) @nogc pure nothrow
1417     {
1418         bt(_ptr, pos) ? btr(_ptr, pos) : bts(_ptr, pos);
1419     }
1420 
1421     ///
1422     @system pure nothrow unittest
1423     {
1424         auto ax = BitArray([1, 0, 0, 1]);
1425         ax.flip(0);
1426         assert(ax[0] == 0);
1427 
1428         bool[200] y;
1429         y[90 .. 130] = true;
1430         auto ay = BitArray(y);
1431         ay.flip(100);
1432         assert(ay[100] == 0);
1433     }
1434 
1435     /**********************************************
1436      * Counts all the set bits in the `BitArray`
1437      */
1438     size_t count() const scope @safe @nogc pure nothrow
1439     {
1440         if (_ptr)
1441         {
1442             size_t bitCount;
1443             foreach (i; 0 .. fullWords)
1444                 bitCount += (() @trusted => countBitsSet(_ptr[i]))();
1445             if (endBits)
1446                 bitCount += (() @trusted => countBitsSet(_ptr[fullWords] & endMask))();
1447             return bitCount;
1448         }
1449         else
1450         {
1451             return 0;
1452         }
1453     }
1454 
1455     ///
1456     @system pure nothrow unittest
1457     {
1458         auto a = BitArray([0, 1, 1, 0, 0, 1, 1]);
1459         assert(a.count == 4);
1460 
1461         BitArray b;
1462         assert(b.count == 0);
1463 
1464         bool[200] boolArray;
1465         boolArray[45 .. 130] = true;
1466         auto c = BitArray(boolArray);
1467         assert(c.count == 85);
1468     }
1469 
1470     /**********************************************
1471      * Duplicates the `BitArray` and its contents.
1472      */
1473     @property BitArray dup() const pure nothrow
1474     {
1475         BitArray ba;
1476 
1477         auto b = _ptr[0 .. dim].dup;
1478         ba._len = _len;
1479         ba._ptr = b.ptr;
1480         return ba;
1481     }
1482 
1483     ///
1484     @system unittest
1485     {
1486         BitArray a;
1487         BitArray b;
1488 
1489         a.length = 3;
1490         a[0] = 1; a[1] = 0; a[2] = 1;
1491         b = a.dup;
1492         assert(b.length == 3);
1493         foreach (i; 0 .. 3)
1494             assert(b[i] == (((i ^ 1) & 1) ? true : false));
1495     }
1496 
1497     /**********************************************
1498      * Support for `foreach` loops for `BitArray`.
1499      */
1500     int opApply(scope int delegate(ref bool) dg)
1501     {
1502         int result;
1503 
1504         foreach (i; 0 .. _len)
1505         {
1506             bool b = opIndex(i);
1507             result = dg(b);
1508             this[i] = b;
1509             if (result)
1510                 break;
1511         }
1512         return result;
1513     }
1514 
1515     /** ditto */
1516     int opApply(scope int delegate(bool) dg) const
1517     {
1518         int result;
1519 
1520         foreach (i; 0 .. _len)
1521         {
1522             immutable b = opIndex(i);
1523             result = dg(b);
1524             if (result)
1525                 break;
1526         }
1527         return result;
1528     }
1529 
1530     /** ditto */
1531     int opApply(scope int delegate(size_t, ref bool) dg)
1532     {
1533         int result;
1534 
1535         foreach (i; 0 .. _len)
1536         {
1537             bool b = opIndex(i);
1538             result = dg(i, b);
1539             this[i] = b;
1540             if (result)
1541                 break;
1542         }
1543         return result;
1544     }
1545 
1546     /** ditto */
1547     int opApply(scope int delegate(size_t, bool) dg) const
1548     {
1549         int result;
1550 
1551         foreach (i; 0 .. _len)
1552         {
1553             immutable b = opIndex(i);
1554             result = dg(i, b);
1555             if (result)
1556                 break;
1557         }
1558         return result;
1559     }
1560 
1561     ///
1562     @system unittest
1563     {
1564         bool[] ba = [1,0,1];
1565 
1566         auto a = BitArray(ba);
1567 
1568         int i;
1569         foreach (b;a)
1570         {
1571             switch (i)
1572             {
1573                 case 0: assert(b == true); break;
1574                 case 1: assert(b == false); break;
1575                 case 2: assert(b == true); break;
1576                 default: assert(0);
1577             }
1578             i++;
1579         }
1580 
1581         foreach (j,b;a)
1582         {
1583             switch (j)
1584             {
1585                 case 0: assert(b == true); break;
1586                 case 1: assert(b == false); break;
1587                 case 2: assert(b == true); break;
1588                 default: assert(0);
1589             }
1590         }
1591     }
1592 
1593 
1594     /**********************************************
1595      * Reverses the bits of the `BitArray`.
1596      */
1597     @property BitArray reverse() @nogc pure nothrow return
1598     out (result)
1599     {
1600         assert(result == this, "the result must be equal to this");
1601     }
1602     do
1603     {
1604         if (_len >= 2)
1605         {
1606             bool t;
1607             size_t lo, hi;
1608 
1609             lo = 0;
1610             hi = _len - 1;
1611             for (; lo < hi; lo++, hi--)
1612             {
1613                 t = this[lo];
1614                 this[lo] = this[hi];
1615                 this[hi] = t;
1616             }
1617         }
1618         return this;
1619     }
1620 
1621     ///
1622     @system unittest
1623     {
1624         BitArray b;
1625         bool[5] data = [1,0,1,1,0];
1626 
1627         b = BitArray(data);
1628         b.reverse;
1629         foreach (i; 0 .. data.length)
1630             assert(b[i] == data[4 - i]);
1631     }
1632 
1633 
1634     /**********************************************
1635      * Sorts the `BitArray`'s elements.
1636      */
1637     @property BitArray sort() @nogc pure nothrow return
1638     out (result)
1639     {
1640         assert(result == this, "the result must be equal to this");
1641     }
1642     do
1643     {
1644         if (_len >= 2)
1645         {
1646             size_t lo, hi;
1647 
1648             lo = 0;
1649             hi = _len - 1;
1650             while (1)
1651             {
1652                 while (1)
1653                 {
1654                     if (lo >= hi)
1655                         goto Ldone;
1656                     if (this[lo] == true)
1657                         break;
1658                     lo++;
1659                 }
1660 
1661                 while (1)
1662                 {
1663                     if (lo >= hi)
1664                         goto Ldone;
1665                     if (this[hi] == false)
1666                         break;
1667                     hi--;
1668                 }
1669 
1670                 this[lo] = false;
1671                 this[hi] = true;
1672 
1673                 lo++;
1674                 hi--;
1675             }
1676         }
1677     Ldone:
1678         return this;
1679     }
1680 
1681     ///
1682     @system unittest
1683     {
1684         size_t x = 0b1100011000;
1685         auto ba = BitArray(10, &x);
1686         ba.sort;
1687         foreach (i; 0 .. 6)
1688             assert(ba[i] == false);
1689         foreach (i; 6 .. 10)
1690             assert(ba[i] == true);
1691     }
1692 
1693 
1694     /***************************************
1695      * Support for operators == and != for `BitArray`.
1696      */
1697     bool opEquals(const ref BitArray a2) const @nogc pure nothrow
1698     {
1699         if (this.length != a2.length)
1700             return false;
1701         auto p1 = this._ptr;
1702         auto p2 = a2._ptr;
1703 
1704         if (p1[0 .. fullWords] != p2[0 .. fullWords])
1705             return false;
1706 
1707         if (!endBits)
1708             return true;
1709 
1710         auto i = fullWords;
1711         return (p1[i] & endMask) == (p2[i] & endMask);
1712     }
1713 
1714     ///
1715     @system unittest
1716     {
1717         bool[] ba = [1,0,1,0,1];
1718         bool[] bb = [1,0,1];
1719         bool[] bc = [1,0,1,0,1,0,1];
1720         bool[] bd = [1,0,1,1,1];
1721         bool[] be = [1,0,1,0,1];
1722         bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
1723         bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
1724 
1725         auto a = BitArray(ba);
1726         auto b = BitArray(bb);
1727         auto c = BitArray(bc);
1728         auto d = BitArray(bd);
1729         auto e = BitArray(be);
1730         auto f = BitArray(bf);
1731         auto g = BitArray(bg);
1732 
1733         assert(a != b);
1734         assert(a != c);
1735         assert(a != d);
1736         assert(a == e);
1737         assert(f != g);
1738     }
1739 
1740     /***************************************
1741      * Supports comparison operators for `BitArray`.
1742      */
1743     int opCmp(BitArray a2) const @nogc pure nothrow
1744     {
1745         const lesser = this.length < a2.length ? &this : &a2;
1746         immutable fullWords = lesser.fullWords;
1747         immutable endBits = lesser.endBits;
1748         auto p1 = this._ptr;
1749         auto p2 = a2._ptr;
1750 
1751         foreach (i; 0 .. fullWords)
1752         {
1753             if (p1[i] != p2[i])
1754             {
1755                 return p1[i] & (size_t(1) << bsf(p1[i] ^ p2[i])) ? 1 : -1;
1756             }
1757         }
1758 
1759         if (endBits)
1760         {
1761             immutable i = fullWords;
1762             immutable diff = p1[i] ^ p2[i];
1763             if (diff)
1764             {
1765                 immutable index = bsf(diff);
1766                 if (index < endBits)
1767                 {
1768                     return p1[i] & (size_t(1) << index) ? 1 : -1;
1769                 }
1770             }
1771         }
1772 
1773         // Standard:
1774         // A bool value can be implicitly converted to any integral type,
1775         // with false becoming 0 and true becoming 1
1776         return (this.length > a2.length) - (this.length < a2.length);
1777     }
1778 
1779     ///
1780     @system unittest
1781     {
1782         bool[] ba = [1,0,1,0,1];
1783         bool[] bb = [1,0,1];
1784         bool[] bc = [1,0,1,0,1,0,1];
1785         bool[] bd = [1,0,1,1,1];
1786         bool[] be = [1,0,1,0,1];
1787         bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
1788         bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0];
1789 
1790         auto a = BitArray(ba);
1791         auto b = BitArray(bb);
1792         auto c = BitArray(bc);
1793         auto d = BitArray(bd);
1794         auto e = BitArray(be);
1795         auto f = BitArray(bf);
1796         auto g = BitArray(bg);
1797 
1798         assert(a >  b);
1799         assert(a >= b);
1800         assert(a <  c);
1801         assert(a <= c);
1802         assert(a <  d);
1803         assert(a <= d);
1804         assert(a == e);
1805         assert(a <= e);
1806         assert(a >= e);
1807         assert(f <  g);
1808         assert(g <= g);
1809     }
1810 
1811     @system unittest
1812     {
1813         bool[] v;
1814         foreach  (i; 1 .. 256)
1815         {
1816             v.length = i;
1817             v[] = false;
1818             auto x = BitArray(v);
1819             v[i-1] = true;
1820             auto y = BitArray(v);
1821             assert(x < y);
1822             assert(x <= y);
1823         }
1824 
1825         BitArray a1, a2;
1826 
1827         for (size_t len = 4; len <= 256; len <<= 1)
1828         {
1829             a1.length = a2.length = len;
1830             a1[len-2] = a2[len-1] = true;
1831             assert(a1 > a2);
1832             a1[len-2] = a2[len-1] = false;
1833         }
1834 
1835         foreach (j; 1 .. a1.length)
1836         {
1837             a1[j-1] = a2[j] = true;
1838             assert(a1 > a2);
1839             a1[j-1] = a2[j] = false;
1840         }
1841     }
1842 
1843     /***************************************
1844      * Support for hashing for `BitArray`.
1845      */
1846     size_t toHash() const @nogc pure nothrow
1847     {
1848         size_t hash = 3557;
1849         auto fullBytes = _len / 8;
1850         foreach (i; 0 .. fullBytes)
1851         {
1852             hash *= 3559;
1853             hash += (cast(byte*) this._ptr)[i];
1854         }
1855         foreach (i; 8*fullBytes .. _len)
1856         {
1857             hash *= 3571;
1858             hash += this[i];
1859         }
1860         return hash;
1861     }
1862 
1863     /***************************************
1864      * Convert to `void[]`.
1865      */
1866     inout(void)[] opCast(T : const void[])() inout @nogc pure nothrow
1867     {
1868         return cast(inout void[]) _ptr[0 .. dim];
1869     }
1870 
1871     /***************************************
1872      * Convert to `size_t[]`.
1873      */
1874     inout(size_t)[] opCast(T : const size_t[])() inout @nogc pure nothrow
1875     {
1876         return _ptr[0 .. dim];
1877     }
1878 
1879     ///
1880     @system unittest
1881     {
1882         import std.array : array;
1883         import std.range : repeat, take;
1884 
1885         // bit array with 300 elements
1886         auto a = BitArray(true.repeat.take(300).array);
1887         size_t[] v = cast(size_t[]) a;
1888         const blockSize = size_t.sizeof * 8;
1889         assert(v.length == (a.length + blockSize - 1) / blockSize);
1890     }
1891 
1892     // https://issues.dlang.org/show_bug.cgi?id=20606
1893     @system unittest
1894     {
1895         import std.meta : AliasSeq;
1896 
1897         static foreach (alias T; AliasSeq!(void, size_t))
1898         {{
1899             BitArray m;
1900             T[] ma = cast(T[]) m;
1901 
1902             const BitArray c;
1903             const(T)[] ca = cast(const T[]) c;
1904 
1905             immutable BitArray i;
1906             immutable(T)[] ia = cast(immutable T[]) i;
1907 
1908             // Cross-mutability
1909             ca = cast(const T[]) m;
1910             ca = cast(const T[]) i;
1911 
1912             // Invalid cast don't compile
1913             static assert(!is(typeof(cast(T[]) c)));
1914             static assert(!is(typeof(cast(T[]) i)));
1915             static assert(!is(typeof(cast(immutable T[]) m)));
1916             static assert(!is(typeof(cast(immutable T[]) c)));
1917         }}
1918     }
1919 
1920     /***************************************
1921      * Support for unary operator ~ for `BitArray`.
1922      */
1923     BitArray opUnary(string op)() const pure nothrow
1924         if (op == "~")
1925     {
1926         auto dim = this.dim;
1927 
1928         BitArray result;
1929         result.length = _len;
1930 
1931         result._ptr[0 .. dim] = ~this._ptr[0 .. dim];
1932 
1933         // Avoid putting garbage in extra bits
1934         // Remove once we zero on length extension
1935         if (endBits)
1936             result._ptr[dim - 1] &= endMask;
1937 
1938         return result;
1939     }
1940 
1941     ///
1942     @system unittest
1943     {
1944         bool[] ba = [1,0,1,0,1];
1945 
1946         auto a = BitArray(ba);
1947         BitArray b = ~a;
1948 
1949         assert(b[0] == 0);
1950         assert(b[1] == 1);
1951         assert(b[2] == 0);
1952         assert(b[3] == 1);
1953         assert(b[4] == 0);
1954     }
1955 
1956 
1957     /***************************************
1958      * Support for binary bitwise operators for `BitArray`.
1959      */
1960     BitArray opBinary(string op)(const BitArray e2) const pure nothrow
1961         if (op == "-" || op == "&" || op == "|" || op == "^")
1962     in
1963     {
1964         assert(e2.length == _len, "e2 must have the same length as this");
1965     }
1966     do
1967     {
1968         auto dim = this.dim;
1969 
1970         BitArray result;
1971         result.length = _len;
1972 
1973         static if (op == "-")
1974             result._ptr[0 .. dim] = this._ptr[0 .. dim] & ~e2._ptr[0 .. dim];
1975         else
1976             mixin("result._ptr[0 .. dim] = this._ptr[0 .. dim]"~op~" e2._ptr[0 .. dim];");
1977 
1978         // Avoid putting garbage in extra bits
1979         // Remove once we zero on length extension
1980         if (endBits)
1981             result._ptr[dim - 1] &= endMask;
1982 
1983         return result;
1984     }
1985 
1986     ///
1987     @system unittest
1988     {
1989         static bool[] ba = [1,0,1,0,1];
1990         static bool[] bb = [1,0,1,1,0];
1991 
1992         auto a = BitArray(ba);
1993         auto b = BitArray(bb);
1994 
1995         BitArray c = a & b;
1996 
1997         assert(c[0] == 1);
1998         assert(c[1] == 0);
1999         assert(c[2] == 1);
2000         assert(c[3] == 0);
2001         assert(c[4] == 0);
2002     }
2003 
2004     ///
2005     @system unittest
2006     {
2007         bool[] ba = [1,0,1,0,1];
2008         bool[] bb = [1,0,1,1,0];
2009 
2010         auto a = BitArray(ba);
2011         auto b = BitArray(bb);
2012 
2013         BitArray c = a | b;
2014 
2015         assert(c[0] == 1);
2016         assert(c[1] == 0);
2017         assert(c[2] == 1);
2018         assert(c[3] == 1);
2019         assert(c[4] == 1);
2020     }
2021 
2022     ///
2023     @system unittest
2024     {
2025         bool[] ba = [1,0,1,0,1];
2026         bool[] bb = [1,0,1,1,0];
2027 
2028         auto a = BitArray(ba);
2029         auto b = BitArray(bb);
2030 
2031         BitArray c = a ^ b;
2032 
2033         assert(c[0] == 0);
2034         assert(c[1] == 0);
2035         assert(c[2] == 0);
2036         assert(c[3] == 1);
2037         assert(c[4] == 1);
2038     }
2039 
2040     ///
2041     @system unittest
2042     {
2043         bool[] ba = [1,0,1,0,1];
2044         bool[] bb = [1,0,1,1,0];
2045 
2046         auto a = BitArray(ba);
2047         auto b = BitArray(bb);
2048 
2049         BitArray c = a - b;
2050 
2051         assert(c[0] == 0);
2052         assert(c[1] == 0);
2053         assert(c[2] == 0);
2054         assert(c[3] == 0);
2055         assert(c[4] == 1);
2056     }
2057 
2058 
2059     /***************************************
2060      * Support for operator op= for `BitArray`.
2061      */
2062     BitArray opOpAssign(string op)(const BitArray e2) @nogc pure nothrow return scope
2063         if (op == "-" || op == "&" || op == "|" || op == "^")
2064     in
2065     {
2066         assert(e2.length == _len, "e2 must have the same length as this");
2067     }
2068     do
2069     {
2070         foreach (i; 0 .. fullWords)
2071         {
2072             static if (op == "-")
2073                 _ptr[i] &= ~e2._ptr[i];
2074             else
2075                 mixin("_ptr[i] "~op~"= e2._ptr[i];");
2076         }
2077         if (!endBits)
2078             return this;
2079 
2080         size_t i = fullWords;
2081         size_t endWord = _ptr[i];
2082         static if (op == "-")
2083             endWord &= ~e2._ptr[i];
2084         else
2085             mixin("endWord "~op~"= e2._ptr[i];");
2086         _ptr[i] = (_ptr[i] & ~endMask) | (endWord & endMask);
2087 
2088         return this;
2089     }
2090 
2091     ///
2092     @system unittest
2093     {
2094         bool[] ba = [1,0,1,0,1,1,0,1,0,1];
2095         bool[] bb = [1,0,1,1,0];
2096         auto a = BitArray(ba);
2097         auto b = BitArray(bb);
2098         BitArray c = a;
2099         c.length = 5;
2100         c &= b;
2101         assert(a[5] == 1);
2102         assert(a[6] == 0);
2103         assert(a[7] == 1);
2104         assert(a[8] == 0);
2105         assert(a[9] == 1);
2106     }
2107 
2108     ///
2109     @system unittest
2110     {
2111         bool[] ba = [1,0,1,0,1];
2112         bool[] bb = [1,0,1,1,0];
2113 
2114         auto a = BitArray(ba);
2115         auto b = BitArray(bb);
2116 
2117         a &= b;
2118         assert(a[0] == 1);
2119         assert(a[1] == 0);
2120         assert(a[2] == 1);
2121         assert(a[3] == 0);
2122         assert(a[4] == 0);
2123     }
2124 
2125     ///
2126     @system unittest
2127     {
2128         bool[] ba = [1,0,1,0,1];
2129         bool[] bb = [1,0,1,1,0];
2130 
2131         auto a = BitArray(ba);
2132         auto b = BitArray(bb);
2133 
2134         a |= b;
2135         assert(a[0] == 1);
2136         assert(a[1] == 0);
2137         assert(a[2] == 1);
2138         assert(a[3] == 1);
2139         assert(a[4] == 1);
2140     }
2141 
2142     ///
2143     @system unittest
2144     {
2145         bool[] ba = [1,0,1,0,1];
2146         bool[] bb = [1,0,1,1,0];
2147 
2148         auto a = BitArray(ba);
2149         auto b = BitArray(bb);
2150 
2151         a ^= b;
2152         assert(a[0] == 0);
2153         assert(a[1] == 0);
2154         assert(a[2] == 0);
2155         assert(a[3] == 1);
2156         assert(a[4] == 1);
2157     }
2158 
2159     ///
2160     @system unittest
2161     {
2162         bool[] ba = [1,0,1,0,1];
2163         bool[] bb = [1,0,1,1,0];
2164 
2165         auto a = BitArray(ba);
2166         auto b = BitArray(bb);
2167 
2168         a -= b;
2169         assert(a[0] == 0);
2170         assert(a[1] == 0);
2171         assert(a[2] == 0);
2172         assert(a[3] == 0);
2173         assert(a[4] == 1);
2174     }
2175 
2176     /***************************************
2177      * Support for operator ~= for `BitArray`.
2178      * $(RED Warning: This will overwrite a bit in the final word
2179      * of the current underlying data regardless of whether it is
2180      * shared between BitArray objects. i.e. D dynamic array
2181      * concatenation semantics are not followed)
2182      */
2183     BitArray opOpAssign(string op)(bool b) pure nothrow return scope
2184         if (op == "~")
2185     {
2186         length = _len + 1;
2187         this[_len - 1] = b;
2188         return this;
2189     }
2190 
2191     ///
2192     @system unittest
2193     {
2194         bool[] ba = [1,0,1,0,1];
2195 
2196         auto a = BitArray(ba);
2197         BitArray b;
2198 
2199         b = (a ~= true);
2200         assert(a[0] == 1);
2201         assert(a[1] == 0);
2202         assert(a[2] == 1);
2203         assert(a[3] == 0);
2204         assert(a[4] == 1);
2205         assert(a[5] == 1);
2206 
2207         assert(b == a);
2208     }
2209 
2210     /***************************************
2211      * ditto
2212      */
2213     BitArray opOpAssign(string op)(BitArray b) pure nothrow return scope
2214         if (op == "~")
2215     {
2216         auto istart = _len;
2217         length = _len + b.length;
2218         for (auto i = istart; i < _len; i++)
2219             this[i] = b[i - istart];
2220         return this;
2221     }
2222 
2223     ///
2224     @system unittest
2225     {
2226         bool[] ba = [1,0];
2227         bool[] bb = [0,1,0];
2228 
2229         auto a = BitArray(ba);
2230         auto b = BitArray(bb);
2231         BitArray c;
2232 
2233         c = (a ~= b);
2234         assert(a.length == 5);
2235         assert(a[0] == 1);
2236         assert(a[1] == 0);
2237         assert(a[2] == 0);
2238         assert(a[3] == 1);
2239         assert(a[4] == 0);
2240 
2241         assert(c == a);
2242     }
2243 
2244     /***************************************
2245      * Support for binary operator ~ for `BitArray`.
2246      */
2247     BitArray opBinary(string op)(bool b) const pure nothrow
2248         if (op == "~")
2249     {
2250         BitArray r;
2251 
2252         r = this.dup;
2253         r.length = _len + 1;
2254         r[_len] = b;
2255         return r;
2256     }
2257 
2258     /** ditto */
2259     BitArray opBinaryRight(string op)(bool b) const pure nothrow
2260         if (op == "~")
2261     {
2262         BitArray r;
2263 
2264         r.length = _len + 1;
2265         r[0] = b;
2266         foreach (i; 0 .. _len)
2267             r[1 + i] = this[i];
2268         return r;
2269     }
2270 
2271     /** ditto */
2272     BitArray opBinary(string op)(BitArray b) const pure nothrow
2273         if (op == "~")
2274     {
2275         BitArray r;
2276 
2277         r = this.dup;
2278         r ~= b;
2279         return r;
2280     }
2281 
2282     ///
2283     @system unittest
2284     {
2285         bool[] ba = [1,0];
2286         bool[] bb = [0,1,0];
2287 
2288         auto a = BitArray(ba);
2289         auto b = BitArray(bb);
2290         BitArray c;
2291 
2292         c = (a ~ b);
2293         assert(c.length == 5);
2294         assert(c[0] == 1);
2295         assert(c[1] == 0);
2296         assert(c[2] == 0);
2297         assert(c[3] == 1);
2298         assert(c[4] == 0);
2299 
2300         c = (a ~ true);
2301         assert(c.length == 3);
2302         assert(c[0] == 1);
2303         assert(c[1] == 0);
2304         assert(c[2] == 1);
2305 
2306         c = (false ~ a);
2307         assert(c.length == 3);
2308         assert(c[0] == 0);
2309         assert(c[1] == 1);
2310         assert(c[2] == 0);
2311     }
2312 
2313     // Rolls double word (upper, lower) to the right by n bits and returns the
2314     // lower word of the result.
2315     private static size_t rollRight()(size_t upper, size_t lower, size_t nbits)
2316         pure @safe nothrow @nogc
2317     in
2318     {
2319         assert(nbits < bitsPerSizeT, "nbits must be less than bitsPerSizeT");
2320     }
2321     do
2322     {
2323         if (nbits == 0)
2324             return lower;
2325         return (upper << (bitsPerSizeT - nbits)) | (lower >> nbits);
2326     }
2327 
2328     @safe unittest
2329     {
2330         static if (size_t.sizeof == 8)
2331         {
2332             size_t x = 0x12345678_90ABCDEF;
2333             size_t y = 0xFEDBCA09_87654321;
2334 
2335             assert(rollRight(x, y, 32) == 0x90ABCDEF_FEDBCA09);
2336             assert(rollRight(y, x, 4) == 0x11234567_890ABCDE);
2337         }
2338         else static if (size_t.sizeof == 4)
2339         {
2340             size_t x = 0x12345678;
2341             size_t y = 0x90ABCDEF;
2342 
2343             assert(rollRight(x, y, 16) == 0x567890AB);
2344             assert(rollRight(y, x, 4) == 0xF1234567);
2345         }
2346         else
2347             static assert(0, "Unsupported size_t width");
2348     }
2349 
2350     // Rolls double word (upper, lower) to the left by n bits and returns the
2351     // upper word of the result.
2352     private static size_t rollLeft()(size_t upper, size_t lower, size_t nbits)
2353         pure @safe nothrow @nogc
2354     in
2355     {
2356         assert(nbits < bitsPerSizeT, "nbits must be less than bitsPerSizeT");
2357     }
2358     do
2359     {
2360         if (nbits == 0)
2361             return upper;
2362         return (upper << nbits) | (lower >> (bitsPerSizeT - nbits));
2363     }
2364 
2365     @safe unittest
2366     {
2367         static if (size_t.sizeof == 8)
2368         {
2369             size_t x = 0x12345678_90ABCDEF;
2370             size_t y = 0xFEDBCA09_87654321;
2371 
2372             assert(rollLeft(x, y, 32) == 0x90ABCDEF_FEDBCA09);
2373             assert(rollLeft(y, x, 4) == 0xEDBCA098_76543211);
2374         }
2375         else static if (size_t.sizeof == 4)
2376         {
2377             size_t x = 0x12345678;
2378             size_t y = 0x90ABCDEF;
2379 
2380             assert(rollLeft(x, y, 16) == 0x567890AB);
2381             assert(rollLeft(y, x, 4) == 0x0ABCDEF1);
2382         }
2383     }
2384 
2385     /**
2386      * Operator `<<=` support.
2387      *
2388      * Shifts all the bits in the array to the left by the given number of
2389      * bits.  The leftmost bits are dropped, and 0's are appended to the end
2390      * to fill up the vacant bits.
2391      *
2392      * $(RED Warning: unused bits in the final word up to the next word
2393      * boundary may be overwritten by this operation. It does not attempt to
2394      * preserve bits past the end of the array.)
2395      */
2396     void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
2397         if (op == "<<")
2398     {
2399         size_t wordsToShift = nbits / bitsPerSizeT;
2400         size_t bitsToShift = nbits % bitsPerSizeT;
2401 
2402         if (wordsToShift < dim)
2403         {
2404             foreach_reverse (i; 1 .. dim - wordsToShift)
2405             {
2406                 _ptr[i + wordsToShift] = rollLeft(_ptr[i], _ptr[i-1],
2407                                                  bitsToShift);
2408             }
2409             _ptr[wordsToShift] = rollLeft(_ptr[0], 0, bitsToShift);
2410         }
2411 
2412         import std.algorithm.comparison : min;
2413         foreach (i; 0 .. min(wordsToShift, dim))
2414         {
2415             _ptr[i] = 0;
2416         }
2417     }
2418 
2419     /**
2420      * Operator `>>=` support.
2421      *
2422      * Shifts all the bits in the array to the right by the given number of
2423      * bits.  The rightmost bits are dropped, and 0's are inserted at the back
2424      * to fill up the vacant bits.
2425      *
2426      * $(RED Warning: unused bits in the final word up to the next word
2427      * boundary may be overwritten by this operation. It does not attempt to
2428      * preserve bits past the end of the array.)
2429      */
2430     void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
2431         if (op == ">>")
2432     {
2433         size_t wordsToShift = nbits / bitsPerSizeT;
2434         size_t bitsToShift = nbits % bitsPerSizeT;
2435 
2436         if (wordsToShift + 1 < dim)
2437         {
2438             foreach (i; 0 .. dim - wordsToShift - 1)
2439             {
2440                 _ptr[i] = rollRight(_ptr[i + wordsToShift + 1],
2441                                    _ptr[i + wordsToShift], bitsToShift);
2442             }
2443         }
2444 
2445         // The last word needs some care, as it must shift in 0's from past the
2446         // end of the array.
2447         if (wordsToShift < dim)
2448         {
2449             if (bitsToShift == 0)
2450                 _ptr[dim - wordsToShift - 1] = _ptr[dim - 1];
2451             else
2452             {
2453                 // Special case: if endBits == 0, then also endMask == 0.
2454                 size_t lastWord = (endBits ? (_ptr[fullWords] & endMask) : _ptr[fullWords - 1]);
2455                 _ptr[dim - wordsToShift - 1] = rollRight(0, lastWord, bitsToShift);
2456             }
2457         }
2458 
2459         import std.algorithm.comparison : min;
2460         foreach (i; 0 .. min(wordsToShift, dim))
2461         {
2462             _ptr[dim - i - 1] = 0;
2463         }
2464     }
2465 
2466     // https://issues.dlang.org/show_bug.cgi?id=17467
2467     @system unittest
2468     {
2469         import std.algorithm.comparison : equal;
2470         import std.range : iota;
2471 
2472         bool[] buf = new bool[64*3];
2473         buf[0 .. 64] = true;
2474         BitArray b = BitArray(buf);
2475         assert(equal(b.bitsSet, iota(0, 64)));
2476         b <<= 64;
2477         assert(equal(b.bitsSet, iota(64, 128)));
2478 
2479         buf = new bool[64*3];
2480         buf[64*2 .. 64*3] = true;
2481         b = BitArray(buf);
2482         assert(equal(b.bitsSet, iota(64*2, 64*3)));
2483         b >>= 64;
2484         assert(equal(b.bitsSet, iota(64, 128)));
2485     }
2486 
2487     // https://issues.dlang.org/show_bug.cgi?id=18134
2488     // shifting right when length is a multiple of 8 * size_t.sizeof.
2489     @system unittest
2490     {
2491         import std.algorithm.comparison : equal;
2492         import std.array : array;
2493         import std.range : repeat, iota;
2494 
2495         immutable r = size_t.sizeof * 8;
2496 
2497         BitArray a = true.repeat(r / 2).array;
2498         a >>= 0;
2499         assert(a.bitsSet.equal(iota(0, r / 2)));
2500         a >>= 1;
2501         assert(a.bitsSet.equal(iota(0, r / 2 - 1)));
2502 
2503         BitArray b = true.repeat(r).array;
2504         b >>= 0;
2505         assert(b.bitsSet.equal(iota(0, r)));
2506         b >>= 1;
2507         assert(b.bitsSet.equal(iota(0, r - 1)));
2508 
2509         BitArray c = true.repeat(2 * r).array;
2510         c >>= 0;
2511         assert(c.bitsSet.equal(iota(0, 2 * r)));
2512         c >>= 10;
2513         assert(c.bitsSet.equal(iota(0, 2 * r - 10)));
2514     }
2515 
2516     ///
2517     @system unittest
2518     {
2519         import std.format : format;
2520 
2521         auto b = BitArray([1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1]);
2522 
2523         b <<= 1;
2524         assert(format("%b", b) == "01100_10101101");
2525 
2526         b >>= 1;
2527         assert(format("%b", b) == "11001_01011010");
2528 
2529         b <<= 4;
2530         assert(format("%b", b) == "00001_10010101");
2531 
2532         b >>= 5;
2533         assert(format("%b", b) == "10010_10100000");
2534 
2535         b <<= 13;
2536         assert(format("%b", b) == "00000_00000000");
2537 
2538         b = BitArray([1, 0, 1, 1, 0, 1, 1, 1]);
2539         b >>= 8;
2540         assert(format("%b", b) == "00000000");
2541 
2542     }
2543 
2544     // Test multi-word case
2545     @system unittest
2546     {
2547         import std.format : format;
2548 
2549         // This has to be long enough to occupy more than one size_t. On 64-bit
2550         // machines, this would be at least 64 bits.
2551         auto b = BitArray([
2552             1, 0, 0, 0, 0, 0, 0, 0,  1, 1, 0, 0, 0, 0, 0, 0,
2553             1, 1, 1, 0, 0, 0, 0, 0,  1, 1, 1, 1, 0, 0, 0, 0,
2554             1, 1, 1, 1, 1, 0, 0, 0,  1, 1, 1, 1, 1, 1, 0, 0,
2555             1, 1, 1, 1, 1, 1, 1, 0,  1, 1, 1, 1, 1, 1, 1, 1,
2556             1, 0, 1, 0, 1, 0, 1, 0,  0, 1, 0, 1, 0, 1, 0, 1,
2557         ]);
2558         b <<= 8;
2559         assert(format("%b", b) ==
2560                "00000000_10000000_"~
2561                "11000000_11100000_"~
2562                "11110000_11111000_"~
2563                "11111100_11111110_"~
2564                "11111111_10101010");
2565 
2566         // Test right shift of more than one size_t's worth of bits
2567         b <<= 68;
2568         assert(format("%b", b) ==
2569                "00000000_00000000_"~
2570                "00000000_00000000_"~
2571                "00000000_00000000_"~
2572                "00000000_00000000_"~
2573                "00000000_00001000");
2574 
2575         b = BitArray([
2576             1, 0, 0, 0, 0, 0, 0, 0,  1, 1, 0, 0, 0, 0, 0, 0,
2577             1, 1, 1, 0, 0, 0, 0, 0,  1, 1, 1, 1, 0, 0, 0, 0,
2578             1, 1, 1, 1, 1, 0, 0, 0,  1, 1, 1, 1, 1, 1, 0, 0,
2579             1, 1, 1, 1, 1, 1, 1, 0,  1, 1, 1, 1, 1, 1, 1, 1,
2580             1, 0, 1, 0, 1, 0, 1, 0,  0, 1, 0, 1, 0, 1, 0, 1,
2581         ]);
2582         b >>= 8;
2583         assert(format("%b", b) ==
2584                "11000000_11100000_"~
2585                "11110000_11111000_"~
2586                "11111100_11111110_"~
2587                "11111111_10101010_"~
2588                "01010101_00000000");
2589 
2590         // Test left shift of more than 1 size_t's worth of bits
2591         b >>= 68;
2592         assert(format("%b", b) ==
2593                "01010000_00000000_"~
2594                "00000000_00000000_"~
2595                "00000000_00000000_"~
2596                "00000000_00000000_"~
2597                "00000000_00000000");
2598     }
2599 
2600     /***************************************
2601      * Return a string representation of this BitArray.
2602      *
2603      * Two format specifiers are supported:
2604      * $(LI $(B %s) which prints the bits as an array, and)
2605      * $(LI $(B %b) which prints the bits as 8-bit byte packets)
2606      * separated with an underscore.
2607      *
2608      * Params:
2609      *     sink = A `char` accepting
2610      *     $(REF_ALTTEXT output range, isOutputRange, std, range, primitives).
2611      *     fmt = A $(REF FormatSpec, std,format) which controls how the data
2612      *     is displayed.
2613      */
2614     void toString(W)(ref W sink, scope const ref FormatSpec!char fmt) const
2615     if (isOutputRange!(W, char))
2616     {
2617         const spec = fmt.spec;
2618         switch (spec)
2619         {
2620             case 'b':
2621                 return formatBitString(sink);
2622             case 's':
2623                 return formatBitArray(sink);
2624             default:
2625                 throw new Exception("Unknown format specifier: %" ~ spec);
2626         }
2627     }
2628 
2629     ///
2630     @system pure unittest
2631     {
2632         import std.format : format;
2633 
2634         auto b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2635 
2636         auto s1 = format("%s", b);
2637         assert(s1 == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2638 
2639         auto s2 = format("%b", b);
2640         assert(s2 == "00001111_00001111");
2641     }
2642 
2643     /***************************************
2644      * Return a lazy range of the indices of set bits.
2645      */
2646     @property auto bitsSet() const nothrow
2647     {
2648         import std.algorithm.iteration : filter, map, joiner;
2649         import std.range : iota, chain;
2650 
2651         return chain(
2652             iota(fullWords)
2653                 .filter!(i => _ptr[i])()
2654                 .map!(i => BitsSet!size_t(_ptr[i], i * bitsPerSizeT))()
2655                 .joiner(),
2656             iota(fullWords * bitsPerSizeT, _len)
2657                 .filter!(i => this[i])()
2658         );
2659     }
2660 
2661     ///
2662     @system unittest
2663     {
2664         import std.algorithm.comparison : equal;
2665 
2666         auto b1 = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2667         assert(b1.bitsSet.equal([4, 5, 6, 7, 12, 13, 14, 15]));
2668 
2669         BitArray b2;
2670         b2.length = 1000;
2671         b2[333] = true;
2672         b2[666] = true;
2673         b2[999] = true;
2674         assert(b2.bitsSet.equal([333, 666, 999]));
2675     }
2676 
2677     @system unittest
2678     {
2679         import std.algorithm.comparison : equal;
2680         import std.range : iota;
2681 
2682         BitArray b;
2683         enum wordBits = size_t.sizeof * 8;
2684         b = BitArray([size_t.max], 0);
2685         assert(b.bitsSet.empty);
2686         b = BitArray([size_t.max], 1);
2687         assert(b.bitsSet.equal([0]));
2688         b = BitArray([size_t.max], wordBits);
2689         assert(b.bitsSet.equal(iota(wordBits)));
2690         b = BitArray([size_t.max, size_t.max], wordBits);
2691         assert(b.bitsSet.equal(iota(wordBits)));
2692         b = BitArray([size_t.max, size_t.max], wordBits + 1);
2693         assert(b.bitsSet.equal(iota(wordBits + 1)));
2694         b = BitArray([size_t.max, size_t.max], wordBits * 2);
2695         assert(b.bitsSet.equal(iota(wordBits * 2)));
2696     }
2697 
2698     // https://issues.dlang.org/show_bug.cgi?id=20241
2699     @system unittest
2700     {
2701         BitArray ba;
2702         ba.length = 2;
2703         ba[1] = 1;
2704         ba.length = 1;
2705         assert(ba.bitsSet.empty);
2706     }
2707 
2708     private void formatBitString(Writer)(auto ref Writer sink) const
2709     {
2710         if (!length)
2711             return;
2712 
2713         auto leftover = _len % 8;
2714         foreach (idx; 0 .. leftover)
2715         {
2716             put(sink, cast(char)(this[idx] + '0'));
2717         }
2718 
2719         if (leftover && _len > 8)
2720             put(sink, "_");
2721 
2722         size_t count;
2723         foreach (idx; leftover .. _len)
2724         {
2725             put(sink, cast(char)(this[idx] + '0'));
2726             if (++count == 8 && idx != _len - 1)
2727             {
2728                 put(sink, "_");
2729                 count = 0;
2730             }
2731         }
2732     }
2733 
2734     private void formatBitArray(Writer)(auto ref Writer sink) const
2735     {
2736         put(sink, "[");
2737         foreach (idx; 0 .. _len)
2738         {
2739             put(sink, cast(char)(this[idx] + '0'));
2740             if (idx + 1 < _len)
2741                 put(sink, ", ");
2742         }
2743         put(sink, "]");
2744     }
2745 
2746     // https://issues.dlang.org/show_bug.cgi?id=20639
2747     // Separate @nogc test because public tests use array literals
2748     // (and workarounds needlessly uglify those examples)
2749     @system @nogc unittest
2750     {
2751         size_t[2] buffer;
2752         BitArray b = BitArray(buffer[], buffer.sizeof * 8);
2753 
2754         b[] = true;
2755         b[0 .. 1] = true;
2756         b.flip();
2757         b.flip(1);
2758         cast(void) b.count();
2759     }
2760 }
2761 
2762 /// Slicing & bitsSet
2763 @system unittest
2764 {
2765     import std.algorithm.comparison : equal;
2766     import std.range : iota;
2767 
2768     bool[] buf = new bool[64 * 3];
2769     buf[0 .. 64] = true;
2770     BitArray b = BitArray(buf);
2771     assert(b.bitsSet.equal(iota(0, 64)));
2772     b <<= 64;
2773     assert(b.bitsSet.equal(iota(64, 128)));
2774 }
2775 
2776 /// Concatenation and appending
2777 @system unittest
2778 {
2779     import std.algorithm.comparison : equal;
2780 
2781     auto b = BitArray([1, 0]);
2782     b ~= true;
2783     assert(b[2] == 1);
2784     b ~= BitArray([0, 1]);
2785     auto c = BitArray([1, 0, 1, 0, 1]);
2786     assert(b == c);
2787     assert(b.bitsSet.equal([0, 2, 4]));
2788 }
2789 
2790 /// Bit flipping
2791 @system unittest
2792 {
2793     import std.algorithm.comparison : equal;
2794 
2795     auto b = BitArray([1, 1, 0, 1]);
2796     b &= BitArray([0, 1, 1, 0]);
2797     assert(b.bitsSet.equal([1]));
2798     b.flip;
2799     assert(b.bitsSet.equal([0, 2, 3]));
2800 }
2801 
2802 /// String format of bitarrays
2803 @system unittest
2804 {
2805     import std.format : format;
2806     auto b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2807     assert(format("%b", b) == "1_00001111_00001111");
2808 }
2809 
2810 ///
2811 @system unittest
2812 {
2813     import std.format : format;
2814 
2815     BitArray b;
2816 
2817     b = BitArray([]);
2818     assert(format("%s", b) == "[]");
2819     assert(format("%b", b) is null);
2820 
2821     b = BitArray([1]);
2822     assert(format("%s", b) == "[1]");
2823     assert(format("%b", b) == "1");
2824 
2825     b = BitArray([0, 0, 0, 0]);
2826     assert(format("%b", b) == "0000");
2827 
2828     b = BitArray([0, 0, 0, 0, 1, 1, 1, 1]);
2829     assert(format("%s", b) == "[0, 0, 0, 0, 1, 1, 1, 1]");
2830     assert(format("%b", b) == "00001111");
2831 
2832     b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2833     assert(format("%s", b) == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2834     assert(format("%b", b) == "00001111_00001111");
2835 
2836     b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1]);
2837     assert(format("%b", b) == "1_00001111");
2838 
2839     b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2840     assert(format("%b", b) == "1_00001111_00001111");
2841 }
2842 
2843 @system unittest
2844 {
2845     BitArray a;
2846     a.length = 5;
2847     foreach (ref bool b; a)
2848     {
2849         assert(b == 0);
2850         b = 1;
2851     }
2852     foreach (bool b; a)
2853         assert(b == 1);
2854 }
2855 
2856 /++
2857     Swaps the endianness of the given integral value or character.
2858   +/
2859 T swapEndian(T)(const T val) @safe pure nothrow @nogc
2860 if (isIntegral!T || isSomeChar!T || isBoolean!T)
2861 {
2862     import core.bitop : bswap, byteswap;
2863     static if (val.sizeof == 1)
2864         return val;
2865     else static if (T.sizeof == 2)
2866         return cast(T) byteswap(cast(ushort) val);
2867     else static if (T.sizeof == 4)
2868         return cast(T) bswap(cast(uint) val);
2869     else static if (T.sizeof == 8)
2870         return cast(T) bswap(cast(ulong) val);
2871     else
2872         static assert(0, T.stringof ~ " unsupported by swapEndian.");
2873 }
2874 
2875 ///
2876 @safe unittest
2877 {
2878     assert(42.swapEndian == 704643072);
2879     assert(42.swapEndian.swapEndian == 42); // reflexive
2880     assert(1.swapEndian == 16777216);
2881 
2882     assert(true.swapEndian == true);
2883     assert(byte(10).swapEndian == 10);
2884     assert(char(10).swapEndian == 10);
2885 
2886     assert(ushort(10).swapEndian == 2560);
2887     assert(long(10).swapEndian == 720575940379279360);
2888     assert(ulong(10).swapEndian == 720575940379279360);
2889 }
2890 
2891 @safe unittest
2892 {
2893     import std.meta;
2894     import std.stdio;
2895     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, char, wchar, dchar))
2896     {{
2897         scope(failure) writeln("Failed type: ", T.stringof);
2898         T val;
2899         const T cval;
2900         immutable T ival;
2901 
2902         assert(swapEndian(swapEndian(val)) == val);
2903         assert(swapEndian(swapEndian(cval)) == cval);
2904         assert(swapEndian(swapEndian(ival)) == ival);
2905         assert(swapEndian(swapEndian(T.min)) == T.min);
2906         assert(swapEndian(swapEndian(T.max)) == T.max);
2907 
2908         // Check CTFE compiles.
2909         static assert(swapEndian(swapEndian(T(1))) is T(1));
2910 
2911         foreach (i; 2 .. 10)
2912         {
2913             immutable T maxI = cast(T)(T.max / i);
2914             immutable T minI = cast(T)(T.min / i);
2915 
2916             assert(swapEndian(swapEndian(maxI)) == maxI);
2917 
2918             static if (isSigned!T)
2919                 assert(swapEndian(swapEndian(minI)) == minI);
2920         }
2921 
2922         static if (isSigned!T)
2923             assert(swapEndian(swapEndian(cast(T) 0)) == 0);
2924 
2925         // used to trigger https://issues.dlang.org/show_bug.cgi?id=6354
2926         static if (T.sizeof > 1 && isUnsigned!T)
2927         {
2928             T left = 0xffU;
2929             left <<= (T.sizeof - 1) * 8;
2930             T right = 0xffU;
2931 
2932             for (size_t i = 1; i < T.sizeof; ++i)
2933             {
2934                 assert(swapEndian(left) == right);
2935                 assert(swapEndian(right) == left);
2936                 left >>= 8;
2937                 right <<= 8;
2938             }
2939         }
2940     }}
2941 }
2942 
2943 
2944 private union EndianSwapper(T)
2945 if (canSwapEndianness!T)
2946 {
2947     T value;
2948     ubyte[T.sizeof] array;
2949 
2950     static if (is(immutable FloatingPointTypeOf!(T) == immutable float))
2951         uint  intValue;
2952     else static if (is(immutable FloatingPointTypeOf!(T) == immutable double))
2953         ulong intValue;
2954 
2955 }
2956 
2957 // Can't use EndianSwapper union during CTFE.
2958 private auto ctfeRead(T)(const ubyte[T.sizeof] array)
2959 if (__traits(isIntegral, T))
2960 {
2961     Unqual!T result;
2962     version (LittleEndian)
2963         foreach_reverse (b; array)
2964             result = cast(Unqual!T) ((result << 8) | b);
2965     else
2966         foreach (b; array)
2967             result = cast(Unqual!T) ((result << 8) | b);
2968     return cast(T) result;
2969 }
2970 
2971 // Can't use EndianSwapper union during CTFE.
2972 private auto ctfeBytes(T)(const T value)
2973 if (__traits(isIntegral, T))
2974 {
2975     ubyte[T.sizeof] result;
2976     Unqual!T tmp = value;
2977     version (LittleEndian)
2978     {
2979         foreach (i; 0 .. T.sizeof)
2980         {
2981             result[i] = cast(ubyte) tmp;
2982             tmp = cast(Unqual!T) (tmp >>> 8);
2983         }
2984     }
2985     else
2986     {
2987         foreach_reverse (i; 0 .. T.sizeof)
2988         {
2989             result[i] = cast(ubyte) tmp;
2990             tmp = cast(Unqual!T) (tmp >>> 8);
2991         }
2992     }
2993     return result;
2994 }
2995 
2996 /++
2997     Converts the given value from the native endianness to big endian and
2998     returns it as a `ubyte[n]` where `n` is the size of the given type.
2999 
3000     Returning a `ubyte[n]` helps prevent accidentally using a swapped value
3001     as a regular one (and in the case of floating point values, it's necessary,
3002     because the FPU will mess up any swapped floating point values. So, you
3003     can't actually have swapped floating point values as floating point values).
3004 
3005     `real` is not supported, because its size is implementation-dependent
3006     and therefore could vary from machine to machine (which could make it
3007     unusable if you tried to transfer it to another machine).
3008   +/
3009 auto nativeToBigEndian(T)(const T val) @safe pure nothrow @nogc
3010 if (canSwapEndianness!T)
3011 {
3012     version (LittleEndian)
3013         return nativeToEndianImpl!true(val);
3014     else
3015         return nativeToEndianImpl!false(val);
3016 }
3017 
3018 ///
3019 @safe unittest
3020 {
3021     int i = 12345;
3022     ubyte[4] swappedI = nativeToBigEndian(i);
3023     assert(i == bigEndianToNative!int(swappedI));
3024 
3025     float f = 123.45f;
3026     ubyte[4] swappedF = nativeToBigEndian(f);
3027     assert(f == bigEndianToNative!float(swappedF));
3028 
3029     const float cf = 123.45f;
3030     ubyte[4] swappedCF = nativeToBigEndian(cf);
3031     assert(cf == bigEndianToNative!float(swappedCF));
3032 
3033     double d = 123.45;
3034     ubyte[8] swappedD = nativeToBigEndian(d);
3035     assert(d == bigEndianToNative!double(swappedD));
3036 
3037     const double cd = 123.45;
3038     ubyte[8] swappedCD = nativeToBigEndian(cd);
3039     assert(cd == bigEndianToNative!double(swappedCD));
3040 }
3041 
3042 private auto nativeToEndianImpl(bool swap, T)(const T val) @safe pure nothrow @nogc
3043 if (__traits(isIntegral, T))
3044 {
3045     if (!__ctfe)
3046     {
3047         static if (swap)
3048             return EndianSwapper!T(swapEndian(val)).array;
3049         else
3050             return EndianSwapper!T(val).array;
3051     }
3052     else
3053     {
3054         // Can't use EndianSwapper in CTFE.
3055         static if (swap)
3056             return ctfeBytes(swapEndian(val));
3057         else
3058             return ctfeBytes(val);
3059     }
3060 }
3061 
3062 @safe unittest
3063 {
3064     import std.meta;
3065     import std.stdio;
3066     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3067                          char, wchar, dchar
3068         /* The trouble here is with floats and doubles being compared against nan
3069          * using a bit compare. There are two kinds of nans, quiet and signaling.
3070          * When a nan passes through the x87, it converts signaling to quiet.
3071          * When a nan passes through the XMM, it does not convert signaling to quiet.
3072          * float.init is a signaling nan.
3073          * The binary API sometimes passes the data through the XMM, sometimes through
3074          * the x87, meaning these will fail the 'is' bit compare under some circumstances.
3075          * I cannot think of a fix for this that makes consistent sense.
3076          */
3077                           /*,float, double*/))
3078     {{
3079         scope(failure) writeln("Failed type: ", T.stringof);
3080         T val;
3081         const T cval;
3082         immutable T ival;
3083 
3084         //is instead of == because of NaN for floating point values.
3085         assert(bigEndianToNative!T(nativeToBigEndian(val)) is val);
3086         assert(bigEndianToNative!T(nativeToBigEndian(cval)) is cval);
3087         assert(bigEndianToNative!T(nativeToBigEndian(ival)) is ival);
3088         assert(bigEndianToNative!T(nativeToBigEndian(T.min)) == T.min);
3089         assert(bigEndianToNative!T(nativeToBigEndian(T.max)) == T.max);
3090 
3091         //Check CTFE compiles.
3092         static assert(bigEndianToNative!T(nativeToBigEndian(T(1))) is T(1));
3093 
3094         static if (isSigned!T)
3095             assert(bigEndianToNative!T(nativeToBigEndian(cast(T) 0)) == 0);
3096 
3097         static if (!is(T == bool))
3098         {
3099             foreach (i; [2, 4, 6, 7, 9, 11])
3100             {
3101                 immutable T maxI = cast(T)(T.max / i);
3102                 immutable T minI = cast(T)(T.min / i);
3103 
3104                 assert(bigEndianToNative!T(nativeToBigEndian(maxI)) == maxI);
3105 
3106                 static if (T.sizeof > 1)
3107                     assert(nativeToBigEndian(maxI) != nativeToLittleEndian(maxI));
3108                 else
3109                     assert(nativeToBigEndian(maxI) == nativeToLittleEndian(maxI));
3110 
3111                 static if (isSigned!T)
3112                 {
3113                     assert(bigEndianToNative!T(nativeToBigEndian(minI)) == minI);
3114 
3115                     static if (T.sizeof > 1)
3116                         assert(nativeToBigEndian(minI) != nativeToLittleEndian(minI));
3117                     else
3118                         assert(nativeToBigEndian(minI) == nativeToLittleEndian(minI));
3119                 }
3120             }
3121         }
3122 
3123         static if (isUnsigned!T || T.sizeof == 1 || is(T == wchar))
3124             assert(nativeToBigEndian(T.max) == nativeToLittleEndian(T.max));
3125         else
3126             assert(nativeToBigEndian(T.max) != nativeToLittleEndian(T.max));
3127 
3128         static if (isUnsigned!T || T.sizeof == 1 || isSomeChar!T)
3129             assert(nativeToBigEndian(T.min) == nativeToLittleEndian(T.min));
3130         else
3131             assert(nativeToBigEndian(T.min) != nativeToLittleEndian(T.min));
3132     }}
3133 }
3134 
3135 
3136 /++
3137     Converts the given value from big endian to the native endianness and
3138     returns it. The value is given as a `ubyte[n]` where `n` is the size
3139     of the target type. You must give the target type as a template argument,
3140     because there are multiple types with the same size and so the type of the
3141     argument is not enough to determine the return type.
3142 
3143     Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3144     as a regular one (and in the case of floating point values, it's necessary,
3145     because the FPU will mess up any swapped floating point values. So, you
3146     can't actually have swapped floating point values as floating point values).
3147   +/
3148 T bigEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
3149 if (canSwapEndianness!T && n == T.sizeof)
3150 {
3151     version (LittleEndian)
3152         return endianToNativeImpl!(true, T, n)(val);
3153     else
3154         return endianToNativeImpl!(false, T, n)(val);
3155 }
3156 
3157 ///
3158 @safe unittest
3159 {
3160     ushort i = 12345;
3161     ubyte[2] swappedI = nativeToBigEndian(i);
3162     assert(i == bigEndianToNative!ushort(swappedI));
3163 
3164     dchar c = 'D';
3165     ubyte[4] swappedC = nativeToBigEndian(c);
3166     assert(c == bigEndianToNative!dchar(swappedC));
3167 }
3168 
3169 /++
3170     Converts the given value from the native endianness to little endian and
3171     returns it as a `ubyte[n]` where `n` is the size of the given type.
3172 
3173     Returning a `ubyte[n]` helps prevent accidentally using a swapped value
3174     as a regular one (and in the case of floating point values, it's necessary,
3175     because the FPU will mess up any swapped floating point values. So, you
3176     can't actually have swapped floating point values as floating point values).
3177   +/
3178 auto nativeToLittleEndian(T)(const T val) @safe pure nothrow @nogc
3179 if (canSwapEndianness!T)
3180 {
3181     version (BigEndian)
3182         return nativeToEndianImpl!true(val);
3183     else
3184         return nativeToEndianImpl!false(val);
3185 }
3186 
3187 ///
3188 @safe unittest
3189 {
3190     int i = 12345;
3191     ubyte[4] swappedI = nativeToLittleEndian(i);
3192     assert(i == littleEndianToNative!int(swappedI));
3193 
3194     double d = 123.45;
3195     ubyte[8] swappedD = nativeToLittleEndian(d);
3196     assert(d == littleEndianToNative!double(swappedD));
3197 }
3198 
3199 @safe unittest
3200 {
3201     import std.meta;
3202     import std.stdio;
3203     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3204                          char, wchar, dchar/*,
3205                          float, double*/))
3206     {{
3207         scope(failure) writeln("Failed type: ", T.stringof);
3208         T val;
3209         const T cval;
3210         immutable T ival;
3211 
3212         //is instead of == because of NaN for floating point values.
3213         assert(littleEndianToNative!T(nativeToLittleEndian(val)) is val);
3214         assert(littleEndianToNative!T(nativeToLittleEndian(cval)) is cval);
3215         assert(littleEndianToNative!T(nativeToLittleEndian(ival)) is ival);
3216         assert(littleEndianToNative!T(nativeToLittleEndian(T.min)) == T.min);
3217         assert(littleEndianToNative!T(nativeToLittleEndian(T.max)) == T.max);
3218 
3219         //Check CTFE compiles.
3220         static assert(littleEndianToNative!T(nativeToLittleEndian(T(1))) is T(1));
3221 
3222         static if (isSigned!T)
3223             assert(littleEndianToNative!T(nativeToLittleEndian(cast(T) 0)) == 0);
3224 
3225         static if (!is(T == bool))
3226         {
3227             foreach (i; 2 .. 10)
3228             {
3229                 immutable T maxI = cast(T)(T.max / i);
3230                 immutable T minI = cast(T)(T.min / i);
3231 
3232                 assert(littleEndianToNative!T(nativeToLittleEndian(maxI)) == maxI);
3233 
3234                 static if (isSigned!T)
3235                     assert(littleEndianToNative!T(nativeToLittleEndian(minI)) == minI);
3236             }
3237         }
3238     }}
3239 }
3240 
3241 
3242 /++
3243     Converts the given value from little endian to the native endianness and
3244     returns it. The value is given as a `ubyte[n]` where `n` is the size
3245     of the target type. You must give the target type as a template argument,
3246     because there are multiple types with the same size and so the type of the
3247     argument is not enough to determine the return type.
3248 
3249     Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3250     as a regular one (and in the case of floating point values, it's necessary,
3251     because the FPU will mess up any swapped floating point values. So, you
3252     can't actually have swapped floating point values as floating point values).
3253 
3254     `real` is not supported, because its size is implementation-dependent
3255     and therefore could vary from machine to machine (which could make it
3256     unusable if you tried to transfer it to another machine).
3257   +/
3258 T littleEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
3259 if (canSwapEndianness!T && n == T.sizeof)
3260 {
3261     version (BigEndian)
3262         return endianToNativeImpl!(true, T, n)(val);
3263     else
3264         return endianToNativeImpl!(false, T, n)(val);
3265 }
3266 
3267 ///
3268 @safe unittest
3269 {
3270     ushort i = 12345;
3271     ubyte[2] swappedI = nativeToLittleEndian(i);
3272     assert(i == littleEndianToNative!ushort(swappedI));
3273 
3274     dchar c = 'D';
3275     ubyte[4] swappedC = nativeToLittleEndian(c);
3276     assert(c == littleEndianToNative!dchar(swappedC));
3277 }
3278 
3279 private T endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @nogc nothrow pure @safe
3280 if (__traits(isIntegral, T) && n == T.sizeof)
3281 {
3282     if (!__ctfe)
3283     {
3284         EndianSwapper!T es = { array: val };
3285         static if (swap)
3286             return swapEndian(es.value);
3287         else
3288             return es.value;
3289     }
3290     else
3291     {
3292         static if (swap)
3293             return swapEndian(ctfeRead!T(val));
3294         else
3295             return ctfeRead!T(val);
3296     }
3297 }
3298 
3299 private auto nativeToEndianImpl(bool swap, T)(const T val) @trusted pure nothrow @nogc
3300 if (isFloatOrDouble!T)
3301 {
3302     if (!__ctfe)
3303     {
3304         EndianSwapper!T es = EndianSwapper!T(val);
3305         static if (swap)
3306             es.intValue = swapEndian(es.intValue);
3307         return es.array;
3308     }
3309     else
3310     {
3311         static if (T.sizeof == 4)
3312             uint intValue = *cast(const uint*) &val;
3313         else static if (T.sizeof == 8)
3314             ulong intValue = *cast(const ulong*) & val;
3315         static if (swap)
3316             intValue = swapEndian(intValue);
3317         return ctfeBytes(intValue);
3318     }
3319 }
3320 
3321 private auto endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc
3322 if (isFloatOrDouble!T && n == T.sizeof)
3323 {
3324     if (!__ctfe)
3325     {
3326         EndianSwapper!T es = { array: val };
3327         static if (swap)
3328             es.intValue = swapEndian(es.intValue);
3329         return es.value;
3330     }
3331     else
3332     {
3333         static if (n == 4)
3334             uint x = ctfeRead!uint(val);
3335         else static if (n == 8)
3336             ulong x = ctfeRead!ulong(val);
3337         static if (swap)
3338             x = swapEndian(x);
3339         return *cast(T*) &x;
3340     }
3341 }
3342 
3343 private template isFloatOrDouble(T)
3344 {
3345     enum isFloatOrDouble = isFloatingPoint!T &&
3346                            !is(immutable FloatingPointTypeOf!T == immutable real);
3347 }
3348 
3349 @safe unittest
3350 {
3351     import std.meta;
3352     static foreach (T; AliasSeq!(float, double))
3353     {
3354         static assert(isFloatOrDouble!(T));
3355         static assert(isFloatOrDouble!(const T));
3356         static assert(isFloatOrDouble!(immutable T));
3357         static assert(isFloatOrDouble!(shared T));
3358         static assert(isFloatOrDouble!(shared(const T)));
3359         static assert(isFloatOrDouble!(shared(immutable T)));
3360     }
3361 
3362     static assert(!isFloatOrDouble!(real));
3363     static assert(!isFloatOrDouble!(const real));
3364     static assert(!isFloatOrDouble!(immutable real));
3365     static assert(!isFloatOrDouble!(shared real));
3366     static assert(!isFloatOrDouble!(shared(const real)));
3367     static assert(!isFloatOrDouble!(shared(immutable real)));
3368 }
3369 
3370 private template canSwapEndianness(T)
3371 {
3372     enum canSwapEndianness = isIntegral!T ||
3373                              isSomeChar!T ||
3374                              isBoolean!T ||
3375                              isFloatOrDouble!T;
3376 }
3377 
3378 @safe unittest
3379 {
3380     import std.meta;
3381     static foreach (T; AliasSeq!(bool, ubyte, byte, ushort, short, uint, int, ulong,
3382                          long, char, wchar, dchar, float, double))
3383     {
3384         static assert(canSwapEndianness!(T));
3385         static assert(canSwapEndianness!(const T));
3386         static assert(canSwapEndianness!(immutable T));
3387         static assert(canSwapEndianness!(shared(T)));
3388         static assert(canSwapEndianness!(shared(const T)));
3389         static assert(canSwapEndianness!(shared(immutable T)));
3390     }
3391 
3392     //!
3393     static foreach (T; AliasSeq!(real, string, wstring, dstring))
3394     {
3395         static assert(!canSwapEndianness!(T));
3396         static assert(!canSwapEndianness!(const T));
3397         static assert(!canSwapEndianness!(immutable T));
3398         static assert(!canSwapEndianness!(shared(T)));
3399         static assert(!canSwapEndianness!(shared(const T)));
3400         static assert(!canSwapEndianness!(shared(immutable T)));
3401     }
3402 }
3403 
3404 /++
3405     Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3406     `T`. The value returned is converted from the given endianness to the
3407     native endianness. The range is not consumed.
3408 
3409     Params:
3410         T     = The integral type to convert the first `T.sizeof` bytes to.
3411         endianness = The endianness that the bytes are assumed to be in.
3412         range = The range to read from.
3413         index = The index to start reading from (instead of starting at the
3414                 front). If index is a pointer, then it is updated to the index
3415                 after the bytes read. The overloads with index are only
3416                 available if `hasSlicing!R` is `true`.
3417   +/
3418 
3419 T peek(T, Endian endianness = Endian.bigEndian, R)(R range)
3420 if (canSwapEndianness!T &&
3421     isForwardRange!R &&
3422     is(ElementType!R : const ubyte))
3423 {
3424     static if (hasSlicing!R)
3425         const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3426     else
3427     {
3428         ubyte[T.sizeof] bytes;
3429         //Make sure that range is not consumed, even if it's a class.
3430         range = range.save;
3431 
3432         foreach (ref e; bytes)
3433         {
3434             e = range.front;
3435             range.popFront();
3436         }
3437     }
3438 
3439     static if (endianness == Endian.bigEndian)
3440         return bigEndianToNative!T(bytes);
3441     else
3442         return littleEndianToNative!T(bytes);
3443 }
3444 
3445 /++ Ditto +/
3446 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t index)
3447 if (canSwapEndianness!T &&
3448     isForwardRange!R &&
3449     hasSlicing!R &&
3450     is(ElementType!R : const ubyte))
3451 {
3452     return peek!(T, endianness)(range, &index);
3453 }
3454 
3455 /++ Ditto +/
3456 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t* index)
3457 if (canSwapEndianness!T &&
3458     isForwardRange!R &&
3459     hasSlicing!R &&
3460     is(ElementType!R : const ubyte))
3461 {
3462     assert(index, "index must not point to null");
3463 
3464     immutable begin = *index;
3465     immutable end = begin + T.sizeof;
3466     const ubyte[T.sizeof] bytes = range[begin .. end];
3467     *index = end;
3468 
3469     static if (endianness == Endian.bigEndian)
3470         return bigEndianToNative!T(bytes);
3471     else
3472         return littleEndianToNative!T(bytes);
3473 }
3474 
3475 ///
3476 @system unittest
3477 {
3478     ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3479     assert(buffer.peek!uint() == 17110537);
3480     assert(buffer.peek!ushort() == 261);
3481     assert(buffer.peek!ubyte() == 1);
3482 
3483     assert(buffer.peek!uint(2) == 369700095);
3484     assert(buffer.peek!ushort(2) == 5641);
3485     assert(buffer.peek!ubyte(2) == 22);
3486 
3487     size_t index = 0;
3488     assert(buffer.peek!ushort(&index) == 261);
3489     assert(index == 2);
3490 
3491     assert(buffer.peek!uint(&index) == 369700095);
3492     assert(index == 6);
3493 
3494     assert(buffer.peek!ubyte(&index) == 8);
3495     assert(index == 7);
3496 }
3497 
3498 ///
3499 @safe unittest
3500 {
3501     import std.algorithm.iteration : filter;
3502     ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7];
3503     auto range = filter!"true"(buffer);
3504     assert(range.peek!uint() == 17110537);
3505     assert(range.peek!ushort() == 261);
3506     assert(range.peek!ubyte() == 1);
3507 }
3508 
3509 @system unittest
3510 {
3511     {
3512         //bool
3513         ubyte[] buffer = [0, 1];
3514         assert(buffer.peek!bool() == false);
3515         assert(buffer.peek!bool(1) == true);
3516 
3517         size_t index = 0;
3518         assert(buffer.peek!bool(&index) == false);
3519         assert(index == 1);
3520 
3521         assert(buffer.peek!bool(&index) == true);
3522         assert(index == 2);
3523     }
3524 
3525     {
3526         //char (8bit)
3527         ubyte[] buffer = [97, 98, 99, 100];
3528         assert(buffer.peek!char() == 'a');
3529         assert(buffer.peek!char(1) == 'b');
3530 
3531         size_t index = 0;
3532         assert(buffer.peek!char(&index) == 'a');
3533         assert(index == 1);
3534 
3535         assert(buffer.peek!char(&index) == 'b');
3536         assert(index == 2);
3537     }
3538 
3539     {
3540         //wchar (16bit - 2x ubyte)
3541         ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3542         assert(buffer.peek!wchar() == 'ą');
3543         assert(buffer.peek!wchar(2) == '”');
3544         assert(buffer.peek!wchar(4) == 'ć');
3545 
3546         size_t index = 0;
3547         assert(buffer.peek!wchar(&index) == 'ą');
3548         assert(index == 2);
3549 
3550         assert(buffer.peek!wchar(&index) == '”');
3551         assert(index == 4);
3552 
3553         assert(buffer.peek!wchar(&index) == 'ć');
3554         assert(index == 6);
3555     }
3556 
3557     {
3558         //dchar (32bit - 4x ubyte)
3559         ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3560         assert(buffer.peek!dchar() == 'ą');
3561         assert(buffer.peek!dchar(4) == '”');
3562         assert(buffer.peek!dchar(8) == 'ć');
3563 
3564         size_t index = 0;
3565         assert(buffer.peek!dchar(&index) == 'ą');
3566         assert(index == 4);
3567 
3568         assert(buffer.peek!dchar(&index) == '”');
3569         assert(index == 8);
3570 
3571         assert(buffer.peek!dchar(&index) == 'ć');
3572         assert(index == 12);
3573     }
3574 
3575     {
3576         //float (32bit - 4x ubyte)
3577         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3578         assert(buffer.peek!float()== 32.0);
3579         assert(buffer.peek!float(4) == 25.0f);
3580 
3581         size_t index = 0;
3582         assert(buffer.peek!float(&index) == 32.0f);
3583         assert(index == 4);
3584 
3585         assert(buffer.peek!float(&index) == 25.0f);
3586         assert(index == 8);
3587     }
3588 
3589     {
3590         //double (64bit - 8x ubyte)
3591         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3592         assert(buffer.peek!double() == 32.0);
3593         assert(buffer.peek!double(8) == 25.0);
3594 
3595         size_t index = 0;
3596         assert(buffer.peek!double(&index) == 32.0);
3597         assert(index == 8);
3598 
3599         assert(buffer.peek!double(&index) == 25.0);
3600         assert(index == 16);
3601     }
3602 
3603     {
3604         //enum
3605         ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3606 
3607         enum Foo
3608         {
3609             one = 10,
3610             two = 20,
3611             three = 30
3612         }
3613 
3614         assert(buffer.peek!Foo() == Foo.one);
3615         assert(buffer.peek!Foo(0) == Foo.one);
3616         assert(buffer.peek!Foo(4) == Foo.two);
3617         assert(buffer.peek!Foo(8) == Foo.three);
3618 
3619         size_t index = 0;
3620         assert(buffer.peek!Foo(&index) == Foo.one);
3621         assert(index == 4);
3622 
3623         assert(buffer.peek!Foo(&index) == Foo.two);
3624         assert(index == 8);
3625 
3626         assert(buffer.peek!Foo(&index) == Foo.three);
3627         assert(index == 12);
3628     }
3629 
3630     {
3631         //enum - bool
3632         ubyte[] buffer = [0, 1];
3633 
3634         enum Bool: bool
3635         {
3636             bfalse = false,
3637             btrue = true,
3638         }
3639 
3640         assert(buffer.peek!Bool() == Bool.bfalse);
3641         assert(buffer.peek!Bool(0) == Bool.bfalse);
3642         assert(buffer.peek!Bool(1) == Bool.btrue);
3643 
3644         size_t index = 0;
3645         assert(buffer.peek!Bool(&index) == Bool.bfalse);
3646         assert(index == 1);
3647 
3648         assert(buffer.peek!Bool(&index) == Bool.btrue);
3649         assert(index == 2);
3650     }
3651 
3652     {
3653         //enum - float
3654         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3655 
3656         enum Float: float
3657         {
3658             one = 32.0f,
3659             two = 25.0f
3660         }
3661 
3662         assert(buffer.peek!Float() == Float.one);
3663         assert(buffer.peek!Float(0) == Float.one);
3664         assert(buffer.peek!Float(4) == Float.two);
3665 
3666         size_t index = 0;
3667         assert(buffer.peek!Float(&index) == Float.one);
3668         assert(index == 4);
3669 
3670         assert(buffer.peek!Float(&index) == Float.two);
3671         assert(index == 8);
3672     }
3673 
3674     {
3675         //enum - double
3676         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3677 
3678         enum Double: double
3679         {
3680             one = 32.0,
3681             two = 25.0
3682         }
3683 
3684         assert(buffer.peek!Double() == Double.one);
3685         assert(buffer.peek!Double(0) == Double.one);
3686         assert(buffer.peek!Double(8) == Double.two);
3687 
3688         size_t index = 0;
3689         assert(buffer.peek!Double(&index) == Double.one);
3690         assert(index == 8);
3691 
3692         assert(buffer.peek!Double(&index) == Double.two);
3693         assert(index == 16);
3694     }
3695 
3696     {
3697         //enum - real
3698         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3699 
3700         enum Real: real
3701         {
3702             one = 32.0,
3703             two = 25.0
3704         }
3705 
3706         static assert(!__traits(compiles, buffer.peek!Real()));
3707     }
3708 }
3709 
3710 /++
3711     Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3712     `T`. The value returned is converted from the given endianness to the
3713     native endianness. The `T.sizeof` bytes which are read are consumed from
3714     the range.
3715 
3716     Params:
3717         T     = The integral type to convert the first `T.sizeof` bytes to.
3718         endianness = The endianness that the bytes are assumed to be in.
3719         range = The range to read from.
3720   +/
3721 T read(T, Endian endianness = Endian.bigEndian, R)(ref R range)
3722 if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const ubyte))
3723 {
3724     static if (hasSlicing!R && is(typeof(R.init[0 .. 0]) : const(ubyte)[]))
3725     {
3726         const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3727         range.popFrontN(T.sizeof);
3728     }
3729     else
3730     {
3731         ubyte[T.sizeof] bytes;
3732 
3733         foreach (ref e; bytes)
3734         {
3735             e = range.front;
3736             range.popFront();
3737         }
3738     }
3739 
3740     static if (endianness == Endian.bigEndian)
3741         return bigEndianToNative!T(bytes);
3742     else
3743         return littleEndianToNative!T(bytes);
3744 }
3745 
3746 ///
3747 @safe unittest
3748 {
3749     import std.range.primitives : empty;
3750     ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3751     assert(buffer.length == 7);
3752 
3753     assert(buffer.read!ushort() == 261);
3754     assert(buffer.length == 5);
3755 
3756     assert(buffer.read!uint() == 369700095);
3757     assert(buffer.length == 1);
3758 
3759     assert(buffer.read!ubyte() == 8);
3760     assert(buffer.empty);
3761 }
3762 
3763 @safe unittest
3764 {
3765     {
3766         //bool
3767         ubyte[] buffer = [0, 1];
3768         assert(buffer.length == 2);
3769 
3770         assert(buffer.read!bool() == false);
3771         assert(buffer.length == 1);
3772 
3773         assert(buffer.read!bool() == true);
3774         assert(buffer.empty);
3775     }
3776 
3777     {
3778         //char (8bit)
3779         ubyte[] buffer = [97, 98, 99];
3780         assert(buffer.length == 3);
3781 
3782         assert(buffer.read!char() == 'a');
3783         assert(buffer.length == 2);
3784 
3785         assert(buffer.read!char() == 'b');
3786         assert(buffer.length == 1);
3787 
3788         assert(buffer.read!char() == 'c');
3789         assert(buffer.empty);
3790     }
3791 
3792     {
3793         //wchar (16bit - 2x ubyte)
3794         ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3795         assert(buffer.length == 6);
3796 
3797         assert(buffer.read!wchar() == 'ą');
3798         assert(buffer.length == 4);
3799 
3800         assert(buffer.read!wchar() == '”');
3801         assert(buffer.length == 2);
3802 
3803         assert(buffer.read!wchar() == 'ć');
3804         assert(buffer.empty);
3805     }
3806 
3807     {
3808         //dchar (32bit - 4x ubyte)
3809         ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3810         assert(buffer.length == 12);
3811 
3812         assert(buffer.read!dchar() == 'ą');
3813         assert(buffer.length == 8);
3814 
3815         assert(buffer.read!dchar() == '”');
3816         assert(buffer.length == 4);
3817 
3818         assert(buffer.read!dchar() == 'ć');
3819         assert(buffer.empty);
3820     }
3821 
3822     {
3823         //float (32bit - 4x ubyte)
3824         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3825         assert(buffer.length == 8);
3826 
3827         assert(buffer.read!float()== 32.0);
3828         assert(buffer.length == 4);
3829 
3830         assert(buffer.read!float() == 25.0f);
3831         assert(buffer.empty);
3832     }
3833 
3834     {
3835         //double (64bit - 8x ubyte)
3836         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3837         assert(buffer.length == 16);
3838 
3839         assert(buffer.read!double() == 32.0);
3840         assert(buffer.length == 8);
3841 
3842         assert(buffer.read!double() == 25.0);
3843         assert(buffer.empty);
3844     }
3845 
3846     {
3847         //enum - uint
3848         ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3849         assert(buffer.length == 12);
3850 
3851         enum Foo
3852         {
3853             one = 10,
3854             two = 20,
3855             three = 30
3856         }
3857 
3858         assert(buffer.read!Foo() == Foo.one);
3859         assert(buffer.length == 8);
3860 
3861         assert(buffer.read!Foo() == Foo.two);
3862         assert(buffer.length == 4);
3863 
3864         assert(buffer.read!Foo() == Foo.three);
3865         assert(buffer.empty);
3866     }
3867 
3868     {
3869         //enum - bool
3870         ubyte[] buffer = [0, 1];
3871         assert(buffer.length == 2);
3872 
3873         enum Bool: bool
3874         {
3875             bfalse = false,
3876             btrue = true,
3877         }
3878 
3879         assert(buffer.read!Bool() == Bool.bfalse);
3880         assert(buffer.length == 1);
3881 
3882         assert(buffer.read!Bool() == Bool.btrue);
3883         assert(buffer.empty);
3884     }
3885 
3886     {
3887         //enum - float
3888         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3889         assert(buffer.length == 8);
3890 
3891         enum Float: float
3892         {
3893             one = 32.0f,
3894             two = 25.0f
3895         }
3896 
3897         assert(buffer.read!Float() == Float.one);
3898         assert(buffer.length == 4);
3899 
3900         assert(buffer.read!Float() == Float.two);
3901         assert(buffer.empty);
3902     }
3903 
3904     {
3905         //enum - double
3906         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3907         assert(buffer.length == 16);
3908 
3909         enum Double: double
3910         {
3911             one = 32.0,
3912             two = 25.0
3913         }
3914 
3915         assert(buffer.read!Double() == Double.one);
3916         assert(buffer.length == 8);
3917 
3918         assert(buffer.read!Double() == Double.two);
3919         assert(buffer.empty);
3920     }
3921 
3922     {
3923         //enum - real
3924         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3925 
3926         enum Real: real
3927         {
3928             one = 32.0,
3929             two = 25.0
3930         }
3931 
3932         static assert(!__traits(compiles, buffer.read!Real()));
3933     }
3934 }
3935 
3936 // https://issues.dlang.org/show_bug.cgi?id=17247
3937 @safe unittest
3938 {
3939     struct UbyteRange
3940     {
3941         ubyte[] impl;
3942         @property bool empty() { return impl.empty; }
3943         @property ubyte front() { return impl.front; }
3944         void popFront() { impl.popFront(); }
3945         @property UbyteRange save() { return this; }
3946 
3947         // N.B. support slicing but do not return ubyte[] slices.
3948         UbyteRange opSlice(size_t start, size_t end)
3949         {
3950             return UbyteRange(impl[start .. end]);
3951         }
3952         @property size_t length() { return impl.length; }
3953         alias opDollar = length;
3954     }
3955     static assert(hasSlicing!UbyteRange);
3956 
3957     auto r = UbyteRange([0x01, 0x00, 0x00, 0x00]);
3958     int x = r.read!(int, Endian.littleEndian)();
3959     assert(x == 1);
3960 }
3961 
3962 
3963 /++
3964     Takes an integral value, converts it to the given endianness, and writes it
3965     to the given range of `ubyte`s as a sequence of `T.sizeof` `ubyte`s
3966     starting at index. `hasSlicing!R` must be `true`.
3967 
3968     Params:
3969         T     = The integral type to convert the first `T.sizeof` bytes to.
3970         endianness = The endianness to _write the bytes in.
3971         range = The range to _write to.
3972         value = The value to _write.
3973         index = The index to start writing to. If index is a pointer, then it
3974                 is updated to the index after the bytes read.
3975   +/
3976 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t index)
3977 if (canSwapEndianness!T &&
3978     isForwardRange!R &&
3979     hasSlicing!R &&
3980     is(ElementType!R : ubyte))
3981 {
3982     write!(T, endianness)(range, value, &index);
3983 }
3984 
3985 /++ Ditto +/
3986 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t* index)
3987 if (canSwapEndianness!T &&
3988     isForwardRange!R &&
3989     hasSlicing!R &&
3990     is(ElementType!R : ubyte))
3991 {
3992     assert(index, "index must not point to null");
3993 
3994     static if (endianness == Endian.bigEndian)
3995         immutable bytes = nativeToBigEndian!T(value);
3996     else
3997         immutable bytes = nativeToLittleEndian!T(value);
3998 
3999     immutable begin = *index;
4000     immutable end = begin + T.sizeof;
4001     *index = end;
4002     range[begin .. end] = bytes[0 .. T.sizeof];
4003 }
4004 
4005 ///
4006 @system unittest
4007 {
4008     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4009     buffer.write!uint(29110231u, 0);
4010     assert(buffer == [1, 188, 47, 215, 0, 0, 0, 0]);
4011 
4012     buffer.write!ushort(927, 0);
4013     assert(buffer == [3, 159, 47, 215, 0, 0, 0, 0]);
4014 
4015     buffer.write!ubyte(42, 0);
4016     assert(buffer == [42, 159, 47, 215, 0, 0, 0, 0]);
4017 }
4018 
4019 ///
4020 @system unittest
4021 {
4022     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0];
4023     buffer.write!uint(142700095u, 2);
4024     assert(buffer == [0, 0, 8, 129, 110, 63, 0, 0, 0]);
4025 
4026     buffer.write!ushort(19839, 2);
4027     assert(buffer == [0, 0, 77, 127, 110, 63, 0, 0, 0]);
4028 
4029     buffer.write!ubyte(132, 2);
4030     assert(buffer == [0, 0, 132, 127, 110, 63, 0, 0, 0]);
4031 }
4032 
4033 ///
4034 @system unittest
4035 {
4036     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4037     size_t index = 0;
4038     buffer.write!ushort(261, &index);
4039     assert(buffer == [1, 5, 0, 0, 0, 0, 0, 0]);
4040     assert(index == 2);
4041 
4042     buffer.write!uint(369700095u, &index);
4043     assert(buffer == [1, 5, 22, 9, 44, 255, 0, 0]);
4044     assert(index == 6);
4045 
4046     buffer.write!ubyte(8, &index);
4047     assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
4048     assert(index == 7);
4049 }
4050 
4051 /// bool
4052 @system unittest
4053 {
4054     ubyte[] buffer = [0, 0];
4055     buffer.write!bool(false, 0);
4056     assert(buffer == [0, 0]);
4057 
4058     buffer.write!bool(true, 0);
4059     assert(buffer == [1, 0]);
4060 
4061     buffer.write!bool(true, 1);
4062     assert(buffer == [1, 1]);
4063 
4064     buffer.write!bool(false, 1);
4065     assert(buffer == [1, 0]);
4066 
4067     size_t index = 0;
4068     buffer.write!bool(false, &index);
4069     assert(buffer == [0, 0]);
4070     assert(index == 1);
4071 
4072     buffer.write!bool(true, &index);
4073     assert(buffer == [0, 1]);
4074     assert(index == 2);
4075 }
4076 
4077 /// char(8-bit)
4078 @system unittest
4079 {
4080     ubyte[] buffer = [0, 0, 0];
4081 
4082     buffer.write!char('a', 0);
4083     assert(buffer == [97, 0, 0]);
4084 
4085     buffer.write!char('b', 1);
4086     assert(buffer == [97, 98, 0]);
4087 
4088     size_t index = 0;
4089     buffer.write!char('a', &index);
4090     assert(buffer == [97, 98, 0]);
4091     assert(index == 1);
4092 
4093     buffer.write!char('b', &index);
4094     assert(buffer == [97, 98, 0]);
4095     assert(index == 2);
4096 
4097     buffer.write!char('c', &index);
4098     assert(buffer == [97, 98, 99]);
4099     assert(index == 3);
4100 }
4101 
4102 /// wchar (16bit - 2x ubyte)
4103 @system unittest
4104 {
4105     ubyte[] buffer = [0, 0, 0, 0];
4106 
4107     buffer.write!wchar('ą', 0);
4108     assert(buffer == [1, 5, 0, 0]);
4109 
4110     buffer.write!wchar('”', 2);
4111     assert(buffer == [1, 5, 32, 29]);
4112 
4113     size_t index = 0;
4114     buffer.write!wchar('ć', &index);
4115     assert(buffer == [1, 7, 32, 29]);
4116     assert(index == 2);
4117 
4118     buffer.write!wchar('ą', &index);
4119     assert(buffer == [1, 7, 1, 5]);
4120     assert(index == 4);
4121 }
4122 
4123 /// dchar (32bit - 4x ubyte)
4124 @system unittest
4125 {
4126     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4127 
4128     buffer.write!dchar('ą', 0);
4129     assert(buffer == [0, 0, 1, 5, 0, 0, 0, 0]);
4130 
4131     buffer.write!dchar('”', 4);
4132     assert(buffer == [0, 0, 1, 5, 0, 0, 32, 29]);
4133 
4134     size_t index = 0;
4135     buffer.write!dchar('ć', &index);
4136     assert(buffer == [0, 0, 1, 7, 0, 0, 32, 29]);
4137     assert(index == 4);
4138 
4139     buffer.write!dchar('ą', &index);
4140     assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
4141     assert(index == 8);
4142 }
4143 
4144 /// float (32bit - 4x ubyte)
4145 @system unittest
4146 {
4147     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4148 
4149     buffer.write!float(32.0f, 0);
4150     assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
4151 
4152     buffer.write!float(25.0f, 4);
4153     assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
4154 
4155     size_t index = 0;
4156     buffer.write!float(25.0f, &index);
4157     assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4158     assert(index == 4);
4159 
4160     buffer.write!float(32.0f, &index);
4161     assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4162     assert(index == 8);
4163 }
4164 
4165 /// double (64bit - 8x ubyte)
4166 @system unittest
4167 {
4168     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4169 
4170     buffer.write!double(32.0, 0);
4171     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4172 
4173     buffer.write!double(25.0, 8);
4174     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4175 
4176     size_t index = 0;
4177     buffer.write!double(25.0, &index);
4178     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4179     assert(index == 8);
4180 
4181     buffer.write!double(32.0, &index);
4182     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4183     assert(index == 16);
4184 }
4185 
4186 /// enum
4187 @system unittest
4188 {
4189     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4190 
4191     enum Foo
4192     {
4193         one = 10,
4194         two = 20,
4195         three = 30
4196     }
4197 
4198     buffer.write!Foo(Foo.one, 0);
4199     assert(buffer == [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0]);
4200 
4201     buffer.write!Foo(Foo.two, 4);
4202     assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0]);
4203 
4204     buffer.write!Foo(Foo.three, 8);
4205     assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4206 
4207     size_t index = 0;
4208     buffer.write!Foo(Foo.three, &index);
4209     assert(buffer == [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30]);
4210     assert(index == 4);
4211 
4212     buffer.write!Foo(Foo.one, &index);
4213     assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30]);
4214     assert(index == 8);
4215 
4216     buffer.write!Foo(Foo.two, &index);
4217     assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
4218     assert(index == 12);
4219 }
4220 
4221 // enum - bool
4222 @system unittest
4223 {
4224     ubyte[] buffer = [0, 0];
4225 
4226     enum Bool: bool
4227     {
4228         bfalse = false,
4229         btrue = true,
4230     }
4231 
4232     buffer.write!Bool(Bool.btrue, 0);
4233     assert(buffer == [1, 0]);
4234 
4235     buffer.write!Bool(Bool.btrue, 1);
4236     assert(buffer == [1, 1]);
4237 
4238     size_t index = 0;
4239     buffer.write!Bool(Bool.bfalse, &index);
4240     assert(buffer == [0, 1]);
4241     assert(index == 1);
4242 
4243     buffer.write!Bool(Bool.bfalse, &index);
4244     assert(buffer == [0, 0]);
4245     assert(index == 2);
4246 }
4247 
4248 /// enum - float
4249 @system unittest
4250 {
4251     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4252 
4253     enum Float: float
4254     {
4255         one = 32.0f,
4256         two = 25.0f
4257     }
4258 
4259     buffer.write!Float(Float.one, 0);
4260     assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
4261 
4262     buffer.write!Float(Float.two, 4);
4263     assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
4264 
4265     size_t index = 0;
4266     buffer.write!Float(Float.two, &index);
4267     assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4268     assert(index == 4);
4269 
4270     buffer.write!Float(Float.one, &index);
4271     assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4272     assert(index == 8);
4273 }
4274 
4275 /// enum - double
4276 @system unittest
4277 {
4278     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4279 
4280     enum Double: double
4281     {
4282         one = 32.0,
4283         two = 25.0
4284     }
4285 
4286     buffer.write!Double(Double.one, 0);
4287     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4288 
4289     buffer.write!Double(Double.two, 8);
4290     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4291 
4292     size_t index = 0;
4293     buffer.write!Double(Double.two, &index);
4294     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4295     assert(index == 8);
4296 
4297     buffer.write!Double(Double.one, &index);
4298     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4299     assert(index == 16);
4300 }
4301 
4302 /// enum - real
4303 @system unittest
4304 {
4305     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4306 
4307     enum Real: real
4308     {
4309         one = 32.0,
4310         two = 25.0
4311     }
4312 
4313     static assert(!__traits(compiles, buffer.write!Real(Real.one)));
4314 }
4315 
4316 
4317 /++
4318     Takes an integral value, converts it to the given endianness, and appends
4319     it to the given range of `ubyte`s (using `put`) as a sequence of
4320     `T.sizeof` `ubyte`s starting at index. `hasSlicing!R` must be
4321     `true`.
4322 
4323     Params:
4324         T     = The integral type to convert the first `T.sizeof` bytes to.
4325         endianness = The endianness to write the bytes in.
4326         range = The range to _append to.
4327         value = The value to _append.
4328   +/
4329 void append(T, Endian endianness = Endian.bigEndian, R)(R range, const T value)
4330 if (canSwapEndianness!T && isOutputRange!(R, ubyte))
4331 {
4332     static if (endianness == Endian.bigEndian)
4333         immutable bytes = nativeToBigEndian!T(value);
4334     else
4335         immutable bytes = nativeToLittleEndian!T(value);
4336 
4337     put(range, bytes[]);
4338 }
4339 
4340 ///
4341 @safe unittest
4342 {
4343     import std.array;
4344     auto buffer = appender!(const ubyte[])();
4345     buffer.append!ushort(261);
4346     assert(buffer.data == [1, 5]);
4347 
4348     buffer.append!uint(369700095u);
4349     assert(buffer.data == [1, 5, 22, 9, 44, 255]);
4350 
4351     buffer.append!ubyte(8);
4352     assert(buffer.data == [1, 5, 22, 9, 44, 255, 8]);
4353 }
4354 
4355 /// bool
4356 @safe unittest
4357 {
4358     import std.array : appender;
4359     auto buffer = appender!(const ubyte[])();
4360 
4361     buffer.append!bool(true);
4362     assert(buffer.data == [1]);
4363 
4364     buffer.append!bool(false);
4365     assert(buffer.data == [1, 0]);
4366 }
4367 
4368 /// char wchar dchar
4369 @safe unittest
4370 {
4371     import std.array : appender;
4372     auto buffer = appender!(const ubyte[])();
4373 
4374     buffer.append!char('a');
4375     assert(buffer.data == [97]);
4376 
4377     buffer.append!char('b');
4378     assert(buffer.data == [97, 98]);
4379 
4380     buffer.append!wchar('ą');
4381     assert(buffer.data == [97, 98, 1, 5]);
4382 
4383     buffer.append!dchar('ą');
4384         assert(buffer.data == [97, 98, 1, 5, 0, 0, 1, 5]);
4385 }
4386 
4387 /// float double
4388 @safe unittest
4389 {
4390     import std.array : appender;
4391     auto buffer = appender!(const ubyte[])();
4392 
4393     buffer.append!float(32.0f);
4394     assert(buffer.data == [66, 0, 0, 0]);
4395 
4396     buffer.append!double(32.0);
4397     assert(buffer.data == [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4398 }
4399 
4400 /// enum
4401 @safe unittest
4402 {
4403     import std.array : appender;
4404     auto buffer = appender!(const ubyte[])();
4405 
4406     enum Foo
4407     {
4408         one = 10,
4409         two = 20,
4410         three = 30
4411     }
4412 
4413     buffer.append!Foo(Foo.one);
4414     assert(buffer.data == [0, 0, 0, 10]);
4415 
4416     buffer.append!Foo(Foo.two);
4417     assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20]);
4418 
4419     buffer.append!Foo(Foo.three);
4420     assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4421 }
4422 
4423 /// enum - bool
4424 @safe unittest
4425 {
4426     import std.array : appender;
4427     auto buffer = appender!(const ubyte[])();
4428 
4429     enum Bool: bool
4430     {
4431         bfalse = false,
4432         btrue = true,
4433     }
4434 
4435     buffer.append!Bool(Bool.btrue);
4436     assert(buffer.data == [1]);
4437 
4438     buffer.append!Bool(Bool.bfalse);
4439     assert(buffer.data == [1, 0]);
4440 
4441     buffer.append!Bool(Bool.btrue);
4442     assert(buffer.data == [1, 0, 1]);
4443 }
4444 
4445 /// enum - float
4446 @safe unittest
4447 {
4448     import std.array : appender;
4449     auto buffer = appender!(const ubyte[])();
4450 
4451     enum Float: float
4452     {
4453         one = 32.0f,
4454         two = 25.0f
4455     }
4456 
4457     buffer.append!Float(Float.one);
4458     assert(buffer.data == [66, 0, 0, 0]);
4459 
4460     buffer.append!Float(Float.two);
4461     assert(buffer.data == [66, 0, 0, 0, 65, 200, 0, 0]);
4462 }
4463 
4464 /// enum - double
4465 @safe unittest
4466 {
4467     import std.array : appender;
4468     auto buffer = appender!(const ubyte[])();
4469 
4470     enum Double: double
4471     {
4472         one = 32.0,
4473         two = 25.0
4474     }
4475 
4476     buffer.append!Double(Double.one);
4477     assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0]);
4478 
4479     buffer.append!Double(Double.two);
4480     assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4481 }
4482 
4483 /// enum - real
4484 @safe unittest
4485 {
4486     import std.array : appender;
4487     auto buffer = appender!(const ubyte[])();
4488 
4489     enum Real: real
4490     {
4491         one = 32.0,
4492         two = 25.0
4493     }
4494 
4495     static assert(!__traits(compiles, buffer.append!Real(Real.one)));
4496 }
4497 
4498 @system unittest
4499 {
4500     import std.array;
4501     import std.format : format;
4502     import std.meta : AliasSeq;
4503     static foreach (endianness; [Endian.bigEndian, Endian.littleEndian])
4504     {{
4505         auto toWrite = appender!(ubyte[])();
4506         alias Types = AliasSeq!(uint, int, long, ulong, short, ubyte, ushort, byte, uint);
4507         ulong[] values = [42, -11, long.max, 1098911981329L, 16, 255, 19012, 2, 17];
4508         assert(Types.length == values.length);
4509 
4510         size_t index = 0;
4511         size_t length = 0;
4512         static foreach (T; Types)
4513         {
4514             toWrite.append!(T, endianness)(cast(T) values[index++]);
4515             length += T.sizeof;
4516         }
4517 
4518         auto toRead = toWrite.data;
4519         assert(toRead.length == length);
4520 
4521         index = 0;
4522         static foreach (T; Types)
4523         {
4524             assert(toRead.peek!(T, endianness)() == values[index], format("Failed Index: %s", index));
4525             assert(toRead.peek!(T, endianness)(0) == values[index], format("Failed Index: %s", index));
4526             assert(toRead.length == length,
4527                    format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4528             assert(toRead.read!(T, endianness)() == values[index], format("Failed Index: %s", index));
4529             length -= T.sizeof;
4530             assert(toRead.length == length,
4531                    format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4532             ++index;
4533         }
4534         assert(toRead.empty);
4535     }}
4536 }
4537 
4538 /**
4539 Counts the number of set bits in the binary representation of `value`.
4540 For signed integers, the sign bit is included in the count.
4541 */
4542 private uint countBitsSet(T)(const T value)
4543 if (isIntegral!T)
4544 {
4545     static if (T.sizeof == 8)
4546     {
4547         import core.bitop : popcnt;
4548         const c = popcnt(cast(ulong) value);
4549     }
4550     else static if (T.sizeof == 4)
4551     {
4552         import core.bitop : popcnt;
4553         const c = popcnt(cast(uint) value);
4554     }
4555     // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
4556     else static if (T.sizeof == 2)
4557     {
4558         uint c = value - ((value >> 1) & 0x5555);
4559         c = ((c >> 2) & 0x3333) + (c & 0X3333);
4560         c = ((c >> 4) + c) & 0x0F0F;
4561         c = ((c >> 8) + c) & 0x00FF;
4562     }
4563     else static if (T.sizeof == 1)
4564     {
4565         uint c = value - ((value >> 1) & 0x55);
4566         c = ((c >> 2) & 0x33) + (c & 0X33);
4567         c = ((c >> 4) + c) & 0x0F;
4568     }
4569     else
4570     {
4571         static assert(false, "countBitsSet only supports 1, 2, 4, or 8 byte sized integers.");
4572     }
4573     return cast(uint) c;
4574 }
4575 
4576 @safe unittest
4577 {
4578     assert(countBitsSet(1) == 1);
4579     assert(countBitsSet(0) == 0);
4580     assert(countBitsSet(int.min) == 1);
4581     assert(countBitsSet(uint.max) == 32);
4582 }
4583 
4584 @safe unittest
4585 {
4586     import std.meta;
4587     static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
4588     {
4589         assert(countBitsSet(cast(T) 0) == 0);
4590         assert(countBitsSet(cast(T) 1) == 1);
4591         assert(countBitsSet(cast(T) 2) == 1);
4592         assert(countBitsSet(cast(T) 3) == 2);
4593         assert(countBitsSet(cast(T) 4) == 1);
4594         assert(countBitsSet(cast(T) 5) == 2);
4595         assert(countBitsSet(cast(T) 127) == 7);
4596         static if (isSigned!T)
4597         {
4598             assert(countBitsSet(cast(T)-1) == 8 * T.sizeof);
4599             assert(countBitsSet(T.min) == 1);
4600         }
4601         else
4602         {
4603             assert(countBitsSet(T.max) == 8 * T.sizeof);
4604         }
4605         // Check CTFE compiles.
4606         static assert(countBitsSet(cast(T) 1) == 1);
4607     }
4608     assert(countBitsSet(1_000_000) == 7);
4609     foreach (i; 0 .. 63)
4610         assert(countBitsSet(1UL << i) == 1);
4611 }
4612 
4613 private struct BitsSet(T)
4614 {
4615     static assert(T.sizeof <= 8, "bitsSet assumes T is no more than 64-bit.");
4616 
4617 @nogc pure nothrow:
4618 
4619     this(T value, size_t startIndex = 0)
4620     {
4621         _value = value;
4622         // Further calculation is only valid and needed when the range is non-empty.
4623         if (!_value)
4624             return;
4625 
4626         import core.bitop : bsf;
4627         immutable trailingZerosCount = bsf(value);
4628         _value >>>= trailingZerosCount;
4629         _index = startIndex + trailingZerosCount;
4630     }
4631 
4632     @property size_t front() const
4633     {
4634         return _index;
4635     }
4636 
4637     @property bool empty() const
4638     {
4639         return !_value;
4640     }
4641 
4642     void popFront()
4643     {
4644         assert(_value, "Cannot call popFront on empty range.");
4645 
4646         _value >>>= 1;
4647         // Further calculation is only valid and needed when the range is non-empty.
4648         if (!_value)
4649             return;
4650 
4651         import core.bitop : bsf;
4652         immutable trailingZerosCount = bsf(_value);
4653         _value >>>= trailingZerosCount;
4654         _index += trailingZerosCount + 1;
4655     }
4656 
4657     @property BitsSet save() const
4658     {
4659         return this;
4660     }
4661 
4662     @property size_t length() const
4663     {
4664         return countBitsSet(_value);
4665     }
4666 
4667     private T _value;
4668     private size_t _index;
4669 }
4670 
4671 /**
4672 Range that iterates the indices of the set bits in `value`.
4673 Index 0 corresponds to the least significant bit.
4674 For signed integers, the highest index corresponds to the sign bit.
4675 */
4676 auto bitsSet(T)(const T value) @nogc pure nothrow
4677 if (isIntegral!T)
4678 {
4679     return BitsSet!T(value);
4680 }
4681 
4682 ///
4683 @safe unittest
4684 {
4685     import std.algorithm.comparison : equal;
4686     import std.range : iota;
4687 
4688     assert(bitsSet(1).equal([0]));
4689     assert(bitsSet(5).equal([0, 2]));
4690     assert(bitsSet(-1).equal(iota(32)));
4691     assert(bitsSet(int.min).equal([31]));
4692 }
4693 
4694 @safe unittest
4695 {
4696     import std.algorithm.comparison : equal;
4697     import std.range : iota;
4698 
4699     import std.meta;
4700     static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
4701     {
4702         assert(bitsSet(cast(T) 0).empty);
4703         assert(bitsSet(cast(T) 1).equal([0]));
4704         assert(bitsSet(cast(T) 2).equal([1]));
4705         assert(bitsSet(cast(T) 3).equal([0, 1]));
4706         assert(bitsSet(cast(T) 4).equal([2]));
4707         assert(bitsSet(cast(T) 5).equal([0, 2]));
4708         assert(bitsSet(cast(T) 127).equal(iota(7)));
4709         static if (isSigned!T)
4710         {
4711             assert(bitsSet(cast(T)-1).equal(iota(8 * T.sizeof)));
4712             assert(bitsSet(T.min).equal([8 * T.sizeof - 1]));
4713         }
4714         else
4715         {
4716             assert(bitsSet(T.max).equal(iota(8 * T.sizeof)));
4717         }
4718     }
4719     assert(bitsSet(1_000_000).equal([6, 9, 14, 16, 17, 18, 19]));
4720     foreach (i; 0 .. 63)
4721         assert(bitsSet(1UL << i).equal([i]));
4722 }