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