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 private union EndianSwapper(T)
2949 if (canSwapEndianness!T)
2950 {
2951     T value;
2952     ubyte[T.sizeof] array;
2953 
2954     static if (is(immutable FloatingPointTypeOf!(T) == immutable float))
2955         uint  intValue;
2956     else static if (is(immutable FloatingPointTypeOf!(T) == immutable double))
2957         ulong intValue;
2958 
2959 }
2960 
2961 // Can't use EndianSwapper union during CTFE.
2962 private auto ctfeRead(T)(const ubyte[T.sizeof] array)
2963 if (__traits(isIntegral, T))
2964 {
2965     Unqual!T result;
2966     version (LittleEndian)
2967         foreach_reverse (b; array)
2968             result = cast() cast(T) ((result << 8) | b);
2969     else
2970         foreach (b; array)
2971             result = cast() cast(T) ((result << 8) | b);
2972     return cast(T) result;
2973 }
2974 
2975 // Can't use EndianSwapper union during CTFE.
2976 private auto ctfeBytes(T)(const T value)
2977 if (__traits(isIntegral, T))
2978 {
2979     ubyte[T.sizeof] result;
2980     Unqual!T tmp = value;
2981     version (LittleEndian)
2982     {
2983         foreach (i; 0 .. T.sizeof)
2984         {
2985             result[i] = cast(ubyte) tmp;
2986             tmp = cast() cast(T) (tmp >>> 8);
2987         }
2988     }
2989     else
2990     {
2991         foreach_reverse (i; 0 .. T.sizeof)
2992         {
2993             result[i] = cast(ubyte) tmp;
2994             tmp = cast()(T) (tmp >>> 8);
2995         }
2996     }
2997     return result;
2998 }
2999 
3000 /++
3001     Converts the given value from the native endianness to big endian and
3002     returns it as a `ubyte[n]` where `n` is the size of the given type.
3003 
3004     Returning a `ubyte[n]` helps prevent accidentally using a swapped value
3005     as a regular one (and in the case of floating point values, it's necessary,
3006     because the FPU will mess up any swapped floating point values. So, you
3007     can't actually have swapped floating point values as floating point values).
3008 
3009     `real` is not supported, because its size is implementation-dependent
3010     and therefore could vary from machine to machine (which could make it
3011     unusable if you tried to transfer it to another machine).
3012   +/
3013 auto nativeToBigEndian(T)(const T val) @safe pure nothrow @nogc
3014 if (canSwapEndianness!T)
3015 {
3016     version (LittleEndian)
3017         return nativeToEndianImpl!true(val);
3018     else
3019         return nativeToEndianImpl!false(val);
3020 }
3021 
3022 ///
3023 @safe unittest
3024 {
3025     int i = 12345;
3026     ubyte[4] swappedI = nativeToBigEndian(i);
3027     assert(i == bigEndianToNative!int(swappedI));
3028 
3029     float f = 123.45f;
3030     ubyte[4] swappedF = nativeToBigEndian(f);
3031     assert(f == bigEndianToNative!float(swappedF));
3032 
3033     const float cf = 123.45f;
3034     ubyte[4] swappedCF = nativeToBigEndian(cf);
3035     assert(cf == bigEndianToNative!float(swappedCF));
3036 
3037     double d = 123.45;
3038     ubyte[8] swappedD = nativeToBigEndian(d);
3039     assert(d == bigEndianToNative!double(swappedD));
3040 
3041     const double cd = 123.45;
3042     ubyte[8] swappedCD = nativeToBigEndian(cd);
3043     assert(cd == bigEndianToNative!double(swappedCD));
3044 }
3045 
3046 private auto nativeToEndianImpl(bool swap, T)(const T val) @safe pure nothrow @nogc
3047 if (__traits(isIntegral, T))
3048 {
3049     if (!__ctfe)
3050     {
3051         static if (swap)
3052             return EndianSwapper!T(swapEndian(val)).array;
3053         else
3054             return EndianSwapper!T(val).array;
3055     }
3056     else
3057     {
3058         // Can't use EndianSwapper in CTFE.
3059         static if (swap)
3060             return ctfeBytes(swapEndian(val));
3061         else
3062             return ctfeBytes(val);
3063     }
3064 }
3065 
3066 @safe unittest
3067 {
3068     import std.meta;
3069     import std.stdio;
3070     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3071                          char, wchar, dchar
3072         /* The trouble here is with floats and doubles being compared against nan
3073          * using a bit compare. There are two kinds of nans, quiet and signaling.
3074          * When a nan passes through the x87, it converts signaling to quiet.
3075          * When a nan passes through the XMM, it does not convert signaling to quiet.
3076          * float.init is a signaling nan.
3077          * The binary API sometimes passes the data through the XMM, sometimes through
3078          * the x87, meaning these will fail the 'is' bit compare under some circumstances.
3079          * I cannot think of a fix for this that makes consistent sense.
3080          */
3081                           /*,float, double*/))
3082     {{
3083         scope(failure) writeln("Failed type: ", T.stringof);
3084         T val;
3085         const T cval;
3086         immutable T ival;
3087 
3088         //is instead of == because of NaN for floating point values.
3089         assert(bigEndianToNative!T(nativeToBigEndian(val)) is val);
3090         assert(bigEndianToNative!T(nativeToBigEndian(cval)) is cval);
3091         assert(bigEndianToNative!T(nativeToBigEndian(ival)) is ival);
3092         assert(bigEndianToNative!T(nativeToBigEndian(T.min)) == T.min);
3093         assert(bigEndianToNative!T(nativeToBigEndian(T.max)) == T.max);
3094 
3095         //Check CTFE compiles.
3096         static assert(bigEndianToNative!T(nativeToBigEndian(T(1))) is T(1));
3097 
3098         static if (isSigned!T)
3099             assert(bigEndianToNative!T(nativeToBigEndian(cast(T) 0)) == 0);
3100 
3101         static if (!is(T == bool))
3102         {
3103             foreach (i; [2, 4, 6, 7, 9, 11])
3104             {
3105                 immutable T maxI = cast(T)(T.max / i);
3106                 immutable T minI = cast(T)(T.min / i);
3107 
3108                 assert(bigEndianToNative!T(nativeToBigEndian(maxI)) == maxI);
3109 
3110                 static if (T.sizeof > 1)
3111                     assert(nativeToBigEndian(maxI) != nativeToLittleEndian(maxI));
3112                 else
3113                     assert(nativeToBigEndian(maxI) == nativeToLittleEndian(maxI));
3114 
3115                 static if (isSigned!T)
3116                 {
3117                     assert(bigEndianToNative!T(nativeToBigEndian(minI)) == minI);
3118 
3119                     static if (T.sizeof > 1)
3120                         assert(nativeToBigEndian(minI) != nativeToLittleEndian(minI));
3121                     else
3122                         assert(nativeToBigEndian(minI) == nativeToLittleEndian(minI));
3123                 }
3124             }
3125         }
3126 
3127         static if (isUnsigned!T || T.sizeof == 1 || is(T == wchar))
3128             assert(nativeToBigEndian(T.max) == nativeToLittleEndian(T.max));
3129         else
3130             assert(nativeToBigEndian(T.max) != nativeToLittleEndian(T.max));
3131 
3132         static if (isUnsigned!T || T.sizeof == 1 || isSomeChar!T)
3133             assert(nativeToBigEndian(T.min) == nativeToLittleEndian(T.min));
3134         else
3135             assert(nativeToBigEndian(T.min) != nativeToLittleEndian(T.min));
3136     }}
3137 }
3138 
3139 
3140 /++
3141     Converts the given value from big endian to the native endianness and
3142     returns it. The value is given as a `ubyte[n]` where `n` is the size
3143     of the target type. You must give the target type as a template argument,
3144     because there are multiple types with the same size and so the type of the
3145     argument is not enough to determine the return type.
3146 
3147     Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3148     as a regular one (and in the case of floating point values, it's necessary,
3149     because the FPU will mess up any swapped floating point values. So, you
3150     can't actually have swapped floating point values as floating point values).
3151   +/
3152 T bigEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
3153 if (canSwapEndianness!T && n == T.sizeof)
3154 {
3155     version (LittleEndian)
3156         return endianToNativeImpl!(true, T, n)(val);
3157     else
3158         return endianToNativeImpl!(false, T, n)(val);
3159 }
3160 
3161 ///
3162 @safe unittest
3163 {
3164     ushort i = 12345;
3165     ubyte[2] swappedI = nativeToBigEndian(i);
3166     assert(i == bigEndianToNative!ushort(swappedI));
3167 
3168     dchar c = 'D';
3169     ubyte[4] swappedC = nativeToBigEndian(c);
3170     assert(c == bigEndianToNative!dchar(swappedC));
3171 }
3172 
3173 /++
3174     Converts the given value from the native endianness to little endian and
3175     returns it as a `ubyte[n]` where `n` is the size of the given type.
3176 
3177     Returning a `ubyte[n]` helps prevent accidentally using a swapped value
3178     as a regular one (and in the case of floating point values, it's necessary,
3179     because the FPU will mess up any swapped floating point values. So, you
3180     can't actually have swapped floating point values as floating point values).
3181   +/
3182 auto nativeToLittleEndian(T)(const T val) @safe pure nothrow @nogc
3183 if (canSwapEndianness!T)
3184 {
3185     version (BigEndian)
3186         return nativeToEndianImpl!true(val);
3187     else
3188         return nativeToEndianImpl!false(val);
3189 }
3190 
3191 ///
3192 @safe unittest
3193 {
3194     int i = 12345;
3195     ubyte[4] swappedI = nativeToLittleEndian(i);
3196     assert(i == littleEndianToNative!int(swappedI));
3197 
3198     double d = 123.45;
3199     ubyte[8] swappedD = nativeToLittleEndian(d);
3200     assert(d == littleEndianToNative!double(swappedD));
3201 }
3202 
3203 @safe unittest
3204 {
3205     import std.meta;
3206     import std.stdio;
3207     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3208                          char, wchar, dchar/*,
3209                          float, double*/))
3210     {{
3211         scope(failure) writeln("Failed type: ", T.stringof);
3212         T val;
3213         const T cval;
3214         immutable T ival;
3215 
3216         //is instead of == because of NaN for floating point values.
3217         assert(littleEndianToNative!T(nativeToLittleEndian(val)) is val);
3218         assert(littleEndianToNative!T(nativeToLittleEndian(cval)) is cval);
3219         assert(littleEndianToNative!T(nativeToLittleEndian(ival)) is ival);
3220         assert(littleEndianToNative!T(nativeToLittleEndian(T.min)) == T.min);
3221         assert(littleEndianToNative!T(nativeToLittleEndian(T.max)) == T.max);
3222 
3223         //Check CTFE compiles.
3224         static assert(littleEndianToNative!T(nativeToLittleEndian(T(1))) is T(1));
3225 
3226         static if (isSigned!T)
3227             assert(littleEndianToNative!T(nativeToLittleEndian(cast(T) 0)) == 0);
3228 
3229         static if (!is(T == bool))
3230         {
3231             foreach (i; 2 .. 10)
3232             {
3233                 immutable T maxI = cast(T)(T.max / i);
3234                 immutable T minI = cast(T)(T.min / i);
3235 
3236                 assert(littleEndianToNative!T(nativeToLittleEndian(maxI)) == maxI);
3237 
3238                 static if (isSigned!T)
3239                     assert(littleEndianToNative!T(nativeToLittleEndian(minI)) == minI);
3240             }
3241         }
3242     }}
3243 }
3244 
3245 
3246 /++
3247     Converts the given value from little endian to the native endianness and
3248     returns it. The value is given as a `ubyte[n]` where `n` is the size
3249     of the target type. You must give the target type as a template argument,
3250     because there are multiple types with the same size and so the type of the
3251     argument is not enough to determine the return type.
3252 
3253     Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3254     as a regular one (and in the case of floating point values, it's necessary,
3255     because the FPU will mess up any swapped floating point values. So, you
3256     can't actually have swapped floating point values as floating point values).
3257 
3258     `real` is not supported, because its size is implementation-dependent
3259     and therefore could vary from machine to machine (which could make it
3260     unusable if you tried to transfer it to another machine).
3261   +/
3262 T littleEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
3263 if (canSwapEndianness!T && n == T.sizeof)
3264 {
3265     version (BigEndian)
3266         return endianToNativeImpl!(true, T, n)(val);
3267     else
3268         return endianToNativeImpl!(false, T, n)(val);
3269 }
3270 
3271 ///
3272 @safe unittest
3273 {
3274     ushort i = 12345;
3275     ubyte[2] swappedI = nativeToLittleEndian(i);
3276     assert(i == littleEndianToNative!ushort(swappedI));
3277 
3278     dchar c = 'D';
3279     ubyte[4] swappedC = nativeToLittleEndian(c);
3280     assert(c == littleEndianToNative!dchar(swappedC));
3281 }
3282 
3283 private T endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @nogc nothrow pure @trusted
3284 if (__traits(isIntegral, T) && n == T.sizeof)
3285 {
3286     if (!__ctfe)
3287     {
3288         EndianSwapper!T es = { array: val };
3289         static if (swap)
3290             return swapEndian(es.value);
3291         else
3292             return es.value;
3293     }
3294     else
3295     {
3296         static if (swap)
3297             return swapEndian(ctfeRead!T(val));
3298         else
3299             return ctfeRead!T(val);
3300     }
3301 }
3302 
3303 private auto nativeToEndianImpl(bool swap, T)(const T val) @trusted pure nothrow @nogc
3304 if (isFloatOrDouble!T)
3305 {
3306     if (!__ctfe)
3307     {
3308         EndianSwapper!T es = EndianSwapper!T(val);
3309         static if (swap)
3310             es.intValue = swapEndian(es.intValue);
3311         return es.array;
3312     }
3313     else
3314     {
3315         static if (T.sizeof == 4)
3316             uint intValue = *cast(const uint*) &val;
3317         else static if (T.sizeof == 8)
3318             ulong intValue = *cast(const ulong*) & val;
3319         static if (swap)
3320             intValue = swapEndian(intValue);
3321         return ctfeBytes(intValue);
3322     }
3323 }
3324 
3325 private auto endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc
3326 if (isFloatOrDouble!T && n == T.sizeof)
3327 {
3328     if (!__ctfe)
3329     {
3330         EndianSwapper!T es = { array: val };
3331         static if (swap)
3332             es.intValue = swapEndian(es.intValue);
3333         return es.value;
3334     }
3335     else
3336     {
3337         static if (n == 4)
3338             uint x = ctfeRead!uint(val);
3339         else static if (n == 8)
3340             ulong x = ctfeRead!ulong(val);
3341         static if (swap)
3342             x = swapEndian(x);
3343         return *cast(T*) &x;
3344     }
3345 }
3346 
3347 private template isFloatOrDouble(T)
3348 {
3349     enum isFloatOrDouble = isFloatingPoint!T &&
3350                            !is(immutable FloatingPointTypeOf!T == immutable real);
3351 }
3352 
3353 @safe unittest
3354 {
3355     import std.meta;
3356     static foreach (T; AliasSeq!(float, double))
3357     {
3358         static assert(isFloatOrDouble!(T));
3359         static assert(isFloatOrDouble!(const T));
3360         static assert(isFloatOrDouble!(immutable T));
3361         static assert(isFloatOrDouble!(shared T));
3362         static assert(isFloatOrDouble!(shared(const T)));
3363         static assert(isFloatOrDouble!(shared(immutable T)));
3364     }
3365 
3366     static assert(!isFloatOrDouble!(real));
3367     static assert(!isFloatOrDouble!(const real));
3368     static assert(!isFloatOrDouble!(immutable real));
3369     static assert(!isFloatOrDouble!(shared real));
3370     static assert(!isFloatOrDouble!(shared(const real)));
3371     static assert(!isFloatOrDouble!(shared(immutable real)));
3372 }
3373 
3374 private template canSwapEndianness(T)
3375 {
3376     enum canSwapEndianness = isIntegral!T ||
3377                              isSomeChar!T ||
3378                              isBoolean!T ||
3379                              isFloatOrDouble!T;
3380 }
3381 
3382 @safe unittest
3383 {
3384     import std.meta;
3385     static foreach (T; AliasSeq!(bool, ubyte, byte, ushort, short, uint, int, ulong,
3386                          long, char, wchar, dchar, float, double))
3387     {
3388         static assert(canSwapEndianness!(T));
3389         static assert(canSwapEndianness!(const T));
3390         static assert(canSwapEndianness!(immutable T));
3391         static assert(canSwapEndianness!(shared(T)));
3392         static assert(canSwapEndianness!(shared(const T)));
3393         static assert(canSwapEndianness!(shared(immutable T)));
3394     }
3395 
3396     //!
3397     static foreach (T; AliasSeq!(real, string, wstring, dstring))
3398     {
3399         static assert(!canSwapEndianness!(T));
3400         static assert(!canSwapEndianness!(const T));
3401         static assert(!canSwapEndianness!(immutable T));
3402         static assert(!canSwapEndianness!(shared(T)));
3403         static assert(!canSwapEndianness!(shared(const T)));
3404         static assert(!canSwapEndianness!(shared(immutable T)));
3405     }
3406 }
3407 
3408 /++
3409     Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3410     `T`. The value returned is converted from the given endianness to the
3411     native endianness. The range is not consumed.
3412 
3413     Params:
3414         T     = The integral type to convert the first `T.sizeof` bytes to.
3415         endianness = The endianness that the bytes are assumed to be in.
3416         range = The range to read from.
3417         index = The index to start reading from (instead of starting at the
3418                 front). If index is a pointer, then it is updated to the index
3419                 after the bytes read. The overloads with index are only
3420                 available if `hasSlicing!R` is `true`.
3421   +/
3422 
3423 T peek(T, Endian endianness = Endian.bigEndian, R)(R range)
3424 if (canSwapEndianness!T &&
3425     isForwardRange!R &&
3426     is(ElementType!R : const ubyte))
3427 {
3428     static if (hasSlicing!R)
3429         const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3430     else
3431     {
3432         ubyte[T.sizeof] bytes;
3433         //Make sure that range is not consumed, even if it's a class.
3434         range = range.save;
3435 
3436         foreach (ref e; bytes)
3437         {
3438             e = range.front;
3439             range.popFront();
3440         }
3441     }
3442 
3443     static if (endianness == Endian.bigEndian)
3444         return bigEndianToNative!T(bytes);
3445     else
3446         return littleEndianToNative!T(bytes);
3447 }
3448 
3449 /++ Ditto +/
3450 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t index)
3451 if (canSwapEndianness!T &&
3452     isForwardRange!R &&
3453     hasSlicing!R &&
3454     is(ElementType!R : const ubyte))
3455 {
3456     return peek!(T, endianness)(range, &index);
3457 }
3458 
3459 /++ Ditto +/
3460 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t* index)
3461 if (canSwapEndianness!T &&
3462     isForwardRange!R &&
3463     hasSlicing!R &&
3464     is(ElementType!R : const ubyte))
3465 {
3466     assert(index, "index must not point to null");
3467 
3468     immutable begin = *index;
3469     immutable end = begin + T.sizeof;
3470     const ubyte[T.sizeof] bytes = range[begin .. end];
3471     *index = end;
3472 
3473     static if (endianness == Endian.bigEndian)
3474         return bigEndianToNative!T(bytes);
3475     else
3476         return littleEndianToNative!T(bytes);
3477 }
3478 
3479 ///
3480 @system unittest
3481 {
3482     ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3483     assert(buffer.peek!uint() == 17110537);
3484     assert(buffer.peek!ushort() == 261);
3485     assert(buffer.peek!ubyte() == 1);
3486 
3487     assert(buffer.peek!uint(2) == 369700095);
3488     assert(buffer.peek!ushort(2) == 5641);
3489     assert(buffer.peek!ubyte(2) == 22);
3490 
3491     size_t index = 0;
3492     assert(buffer.peek!ushort(&index) == 261);
3493     assert(index == 2);
3494 
3495     assert(buffer.peek!uint(&index) == 369700095);
3496     assert(index == 6);
3497 
3498     assert(buffer.peek!ubyte(&index) == 8);
3499     assert(index == 7);
3500 }
3501 
3502 ///
3503 @safe unittest
3504 {
3505     import std.algorithm.iteration : filter;
3506     ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7];
3507     auto range = filter!"true"(buffer);
3508     assert(range.peek!uint() == 17110537);
3509     assert(range.peek!ushort() == 261);
3510     assert(range.peek!ubyte() == 1);
3511 }
3512 
3513 @system unittest
3514 {
3515     {
3516         //bool
3517         ubyte[] buffer = [0, 1];
3518         assert(buffer.peek!bool() == false);
3519         assert(buffer.peek!bool(1) == true);
3520 
3521         size_t index = 0;
3522         assert(buffer.peek!bool(&index) == false);
3523         assert(index == 1);
3524 
3525         assert(buffer.peek!bool(&index) == true);
3526         assert(index == 2);
3527     }
3528 
3529     {
3530         //char (8bit)
3531         ubyte[] buffer = [97, 98, 99, 100];
3532         assert(buffer.peek!char() == 'a');
3533         assert(buffer.peek!char(1) == 'b');
3534 
3535         size_t index = 0;
3536         assert(buffer.peek!char(&index) == 'a');
3537         assert(index == 1);
3538 
3539         assert(buffer.peek!char(&index) == 'b');
3540         assert(index == 2);
3541     }
3542 
3543     {
3544         //wchar (16bit - 2x ubyte)
3545         ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3546         assert(buffer.peek!wchar() == 'ą');
3547         assert(buffer.peek!wchar(2) == '”');
3548         assert(buffer.peek!wchar(4) == 'ć');
3549 
3550         size_t index = 0;
3551         assert(buffer.peek!wchar(&index) == 'ą');
3552         assert(index == 2);
3553 
3554         assert(buffer.peek!wchar(&index) == '”');
3555         assert(index == 4);
3556 
3557         assert(buffer.peek!wchar(&index) == 'ć');
3558         assert(index == 6);
3559     }
3560 
3561     {
3562         //dchar (32bit - 4x ubyte)
3563         ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3564         assert(buffer.peek!dchar() == 'ą');
3565         assert(buffer.peek!dchar(4) == '”');
3566         assert(buffer.peek!dchar(8) == 'ć');
3567 
3568         size_t index = 0;
3569         assert(buffer.peek!dchar(&index) == 'ą');
3570         assert(index == 4);
3571 
3572         assert(buffer.peek!dchar(&index) == '”');
3573         assert(index == 8);
3574 
3575         assert(buffer.peek!dchar(&index) == 'ć');
3576         assert(index == 12);
3577     }
3578 
3579     {
3580         //float (32bit - 4x ubyte)
3581         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3582         assert(buffer.peek!float()== 32.0);
3583         assert(buffer.peek!float(4) == 25.0f);
3584 
3585         size_t index = 0;
3586         assert(buffer.peek!float(&index) == 32.0f);
3587         assert(index == 4);
3588 
3589         assert(buffer.peek!float(&index) == 25.0f);
3590         assert(index == 8);
3591     }
3592 
3593     {
3594         //double (64bit - 8x ubyte)
3595         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3596         assert(buffer.peek!double() == 32.0);
3597         assert(buffer.peek!double(8) == 25.0);
3598 
3599         size_t index = 0;
3600         assert(buffer.peek!double(&index) == 32.0);
3601         assert(index == 8);
3602 
3603         assert(buffer.peek!double(&index) == 25.0);
3604         assert(index == 16);
3605     }
3606 
3607     {
3608         //enum
3609         ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3610 
3611         enum Foo
3612         {
3613             one = 10,
3614             two = 20,
3615             three = 30
3616         }
3617 
3618         assert(buffer.peek!Foo() == Foo.one);
3619         assert(buffer.peek!Foo(0) == Foo.one);
3620         assert(buffer.peek!Foo(4) == Foo.two);
3621         assert(buffer.peek!Foo(8) == Foo.three);
3622 
3623         size_t index = 0;
3624         assert(buffer.peek!Foo(&index) == Foo.one);
3625         assert(index == 4);
3626 
3627         assert(buffer.peek!Foo(&index) == Foo.two);
3628         assert(index == 8);
3629 
3630         assert(buffer.peek!Foo(&index) == Foo.three);
3631         assert(index == 12);
3632     }
3633 
3634     {
3635         //enum - bool
3636         ubyte[] buffer = [0, 1];
3637 
3638         enum Bool: bool
3639         {
3640             bfalse = false,
3641             btrue = true,
3642         }
3643 
3644         assert(buffer.peek!Bool() == Bool.bfalse);
3645         assert(buffer.peek!Bool(0) == Bool.bfalse);
3646         assert(buffer.peek!Bool(1) == Bool.btrue);
3647 
3648         size_t index = 0;
3649         assert(buffer.peek!Bool(&index) == Bool.bfalse);
3650         assert(index == 1);
3651 
3652         assert(buffer.peek!Bool(&index) == Bool.btrue);
3653         assert(index == 2);
3654     }
3655 
3656     {
3657         //enum - float
3658         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3659 
3660         enum Float: float
3661         {
3662             one = 32.0f,
3663             two = 25.0f
3664         }
3665 
3666         assert(buffer.peek!Float() == Float.one);
3667         assert(buffer.peek!Float(0) == Float.one);
3668         assert(buffer.peek!Float(4) == Float.two);
3669 
3670         size_t index = 0;
3671         assert(buffer.peek!Float(&index) == Float.one);
3672         assert(index == 4);
3673 
3674         assert(buffer.peek!Float(&index) == Float.two);
3675         assert(index == 8);
3676     }
3677 
3678     {
3679         //enum - double
3680         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3681 
3682         enum Double: double
3683         {
3684             one = 32.0,
3685             two = 25.0
3686         }
3687 
3688         assert(buffer.peek!Double() == Double.one);
3689         assert(buffer.peek!Double(0) == Double.one);
3690         assert(buffer.peek!Double(8) == Double.two);
3691 
3692         size_t index = 0;
3693         assert(buffer.peek!Double(&index) == Double.one);
3694         assert(index == 8);
3695 
3696         assert(buffer.peek!Double(&index) == Double.two);
3697         assert(index == 16);
3698     }
3699 
3700     {
3701         //enum - real
3702         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3703 
3704         enum Real: real
3705         {
3706             one = 32.0,
3707             two = 25.0
3708         }
3709 
3710         static assert(!__traits(compiles, buffer.peek!Real()));
3711     }
3712 }
3713 
3714 /++
3715     Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3716     `T`. The value returned is converted from the given endianness to the
3717     native endianness. The `T.sizeof` bytes which are read are consumed from
3718     the range.
3719 
3720     Params:
3721         T     = The integral type to convert the first `T.sizeof` bytes to.
3722         endianness = The endianness that the bytes are assumed to be in.
3723         range = The range to read from.
3724   +/
3725 T read(T, Endian endianness = Endian.bigEndian, R)(ref R range)
3726 if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const ubyte))
3727 {
3728     static if (hasSlicing!R && is(typeof(R.init[0 .. 0]) : const(ubyte)[]))
3729     {
3730         const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3731         range.popFrontN(T.sizeof);
3732     }
3733     else
3734     {
3735         ubyte[T.sizeof] bytes;
3736 
3737         foreach (ref e; bytes)
3738         {
3739             e = range.front;
3740             range.popFront();
3741         }
3742     }
3743 
3744     static if (endianness == Endian.bigEndian)
3745         return bigEndianToNative!T(bytes);
3746     else
3747         return littleEndianToNative!T(bytes);
3748 }
3749 
3750 ///
3751 @safe unittest
3752 {
3753     import std.range.primitives : empty;
3754     ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3755     assert(buffer.length == 7);
3756 
3757     assert(buffer.read!ushort() == 261);
3758     assert(buffer.length == 5);
3759 
3760     assert(buffer.read!uint() == 369700095);
3761     assert(buffer.length == 1);
3762 
3763     assert(buffer.read!ubyte() == 8);
3764     assert(buffer.empty);
3765 }
3766 
3767 @safe unittest
3768 {
3769     {
3770         //bool
3771         ubyte[] buffer = [0, 1];
3772         assert(buffer.length == 2);
3773 
3774         assert(buffer.read!bool() == false);
3775         assert(buffer.length == 1);
3776 
3777         assert(buffer.read!bool() == true);
3778         assert(buffer.empty);
3779     }
3780 
3781     {
3782         //char (8bit)
3783         ubyte[] buffer = [97, 98, 99];
3784         assert(buffer.length == 3);
3785 
3786         assert(buffer.read!char() == 'a');
3787         assert(buffer.length == 2);
3788 
3789         assert(buffer.read!char() == 'b');
3790         assert(buffer.length == 1);
3791 
3792         assert(buffer.read!char() == 'c');
3793         assert(buffer.empty);
3794     }
3795 
3796     {
3797         //wchar (16bit - 2x ubyte)
3798         ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3799         assert(buffer.length == 6);
3800 
3801         assert(buffer.read!wchar() == 'ą');
3802         assert(buffer.length == 4);
3803 
3804         assert(buffer.read!wchar() == '”');
3805         assert(buffer.length == 2);
3806 
3807         assert(buffer.read!wchar() == 'ć');
3808         assert(buffer.empty);
3809     }
3810 
3811     {
3812         //dchar (32bit - 4x ubyte)
3813         ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3814         assert(buffer.length == 12);
3815 
3816         assert(buffer.read!dchar() == 'ą');
3817         assert(buffer.length == 8);
3818 
3819         assert(buffer.read!dchar() == '”');
3820         assert(buffer.length == 4);
3821 
3822         assert(buffer.read!dchar() == 'ć');
3823         assert(buffer.empty);
3824     }
3825 
3826     {
3827         //float (32bit - 4x ubyte)
3828         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3829         assert(buffer.length == 8);
3830 
3831         assert(buffer.read!float()== 32.0);
3832         assert(buffer.length == 4);
3833 
3834         assert(buffer.read!float() == 25.0f);
3835         assert(buffer.empty);
3836     }
3837 
3838     {
3839         //double (64bit - 8x ubyte)
3840         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3841         assert(buffer.length == 16);
3842 
3843         assert(buffer.read!double() == 32.0);
3844         assert(buffer.length == 8);
3845 
3846         assert(buffer.read!double() == 25.0);
3847         assert(buffer.empty);
3848     }
3849 
3850     {
3851         //enum - uint
3852         ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3853         assert(buffer.length == 12);
3854 
3855         enum Foo
3856         {
3857             one = 10,
3858             two = 20,
3859             three = 30
3860         }
3861 
3862         assert(buffer.read!Foo() == Foo.one);
3863         assert(buffer.length == 8);
3864 
3865         assert(buffer.read!Foo() == Foo.two);
3866         assert(buffer.length == 4);
3867 
3868         assert(buffer.read!Foo() == Foo.three);
3869         assert(buffer.empty);
3870     }
3871 
3872     {
3873         //enum - bool
3874         ubyte[] buffer = [0, 1];
3875         assert(buffer.length == 2);
3876 
3877         enum Bool: bool
3878         {
3879             bfalse = false,
3880             btrue = true,
3881         }
3882 
3883         assert(buffer.read!Bool() == Bool.bfalse);
3884         assert(buffer.length == 1);
3885 
3886         assert(buffer.read!Bool() == Bool.btrue);
3887         assert(buffer.empty);
3888     }
3889 
3890     {
3891         //enum - float
3892         ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3893         assert(buffer.length == 8);
3894 
3895         enum Float: float
3896         {
3897             one = 32.0f,
3898             two = 25.0f
3899         }
3900 
3901         assert(buffer.read!Float() == Float.one);
3902         assert(buffer.length == 4);
3903 
3904         assert(buffer.read!Float() == Float.two);
3905         assert(buffer.empty);
3906     }
3907 
3908     {
3909         //enum - double
3910         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3911         assert(buffer.length == 16);
3912 
3913         enum Double: double
3914         {
3915             one = 32.0,
3916             two = 25.0
3917         }
3918 
3919         assert(buffer.read!Double() == Double.one);
3920         assert(buffer.length == 8);
3921 
3922         assert(buffer.read!Double() == Double.two);
3923         assert(buffer.empty);
3924     }
3925 
3926     {
3927         //enum - real
3928         ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3929 
3930         enum Real: real
3931         {
3932             one = 32.0,
3933             two = 25.0
3934         }
3935 
3936         static assert(!__traits(compiles, buffer.read!Real()));
3937     }
3938 }
3939 
3940 // https://issues.dlang.org/show_bug.cgi?id=17247
3941 @safe unittest
3942 {
3943     struct UbyteRange
3944     {
3945         ubyte[] impl;
3946         @property bool empty() { return impl.empty; }
3947         @property ubyte front() { return impl.front; }
3948         void popFront() { impl.popFront(); }
3949         @property UbyteRange save() { return this; }
3950 
3951         // N.B. support slicing but do not return ubyte[] slices.
3952         UbyteRange opSlice(size_t start, size_t end)
3953         {
3954             return UbyteRange(impl[start .. end]);
3955         }
3956         @property size_t length() { return impl.length; }
3957         alias opDollar = length;
3958     }
3959     static assert(hasSlicing!UbyteRange);
3960 
3961     auto r = UbyteRange([0x01, 0x00, 0x00, 0x00]);
3962     int x = r.read!(int, Endian.littleEndian)();
3963     assert(x == 1);
3964 }
3965 
3966 
3967 /++
3968     Takes an integral value, converts it to the given endianness, and writes it
3969     to the given range of `ubyte`s as a sequence of `T.sizeof` `ubyte`s
3970     starting at index. `hasSlicing!R` must be `true`.
3971 
3972     Params:
3973         T     = The integral type to convert the first `T.sizeof` bytes to.
3974         endianness = The endianness to _write the bytes in.
3975         range = The range to _write to.
3976         value = The value to _write.
3977         index = The index to start writing to. If index is a pointer, then it
3978                 is updated to the index after the bytes read.
3979   +/
3980 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t index)
3981 if (canSwapEndianness!T &&
3982     isForwardRange!R &&
3983     hasSlicing!R &&
3984     is(ElementType!R : ubyte))
3985 {
3986     write!(T, endianness)(range, value, &index);
3987 }
3988 
3989 /++ Ditto +/
3990 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t* index)
3991 if (canSwapEndianness!T &&
3992     isForwardRange!R &&
3993     hasSlicing!R &&
3994     is(ElementType!R : ubyte))
3995 {
3996     assert(index, "index must not point to null");
3997 
3998     static if (endianness == Endian.bigEndian)
3999         immutable bytes = nativeToBigEndian!T(value);
4000     else
4001         immutable bytes = nativeToLittleEndian!T(value);
4002 
4003     immutable begin = *index;
4004     immutable end = begin + T.sizeof;
4005     *index = end;
4006     range[begin .. end] = bytes[0 .. T.sizeof];
4007 }
4008 
4009 ///
4010 @system unittest
4011 {
4012     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4013     buffer.write!uint(29110231u, 0);
4014     assert(buffer == [1, 188, 47, 215, 0, 0, 0, 0]);
4015 
4016     buffer.write!ushort(927, 0);
4017     assert(buffer == [3, 159, 47, 215, 0, 0, 0, 0]);
4018 
4019     buffer.write!ubyte(42, 0);
4020     assert(buffer == [42, 159, 47, 215, 0, 0, 0, 0]);
4021 }
4022 
4023 ///
4024 @system unittest
4025 {
4026     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0];
4027     buffer.write!uint(142700095u, 2);
4028     assert(buffer == [0, 0, 8, 129, 110, 63, 0, 0, 0]);
4029 
4030     buffer.write!ushort(19839, 2);
4031     assert(buffer == [0, 0, 77, 127, 110, 63, 0, 0, 0]);
4032 
4033     buffer.write!ubyte(132, 2);
4034     assert(buffer == [0, 0, 132, 127, 110, 63, 0, 0, 0]);
4035 }
4036 
4037 ///
4038 @system unittest
4039 {
4040     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4041     size_t index = 0;
4042     buffer.write!ushort(261, &index);
4043     assert(buffer == [1, 5, 0, 0, 0, 0, 0, 0]);
4044     assert(index == 2);
4045 
4046     buffer.write!uint(369700095u, &index);
4047     assert(buffer == [1, 5, 22, 9, 44, 255, 0, 0]);
4048     assert(index == 6);
4049 
4050     buffer.write!ubyte(8, &index);
4051     assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
4052     assert(index == 7);
4053 }
4054 
4055 /// bool
4056 @system unittest
4057 {
4058     ubyte[] buffer = [0, 0];
4059     buffer.write!bool(false, 0);
4060     assert(buffer == [0, 0]);
4061 
4062     buffer.write!bool(true, 0);
4063     assert(buffer == [1, 0]);
4064 
4065     buffer.write!bool(true, 1);
4066     assert(buffer == [1, 1]);
4067 
4068     buffer.write!bool(false, 1);
4069     assert(buffer == [1, 0]);
4070 
4071     size_t index = 0;
4072     buffer.write!bool(false, &index);
4073     assert(buffer == [0, 0]);
4074     assert(index == 1);
4075 
4076     buffer.write!bool(true, &index);
4077     assert(buffer == [0, 1]);
4078     assert(index == 2);
4079 }
4080 
4081 /// char(8-bit)
4082 @system unittest
4083 {
4084     ubyte[] buffer = [0, 0, 0];
4085 
4086     buffer.write!char('a', 0);
4087     assert(buffer == [97, 0, 0]);
4088 
4089     buffer.write!char('b', 1);
4090     assert(buffer == [97, 98, 0]);
4091 
4092     size_t index = 0;
4093     buffer.write!char('a', &index);
4094     assert(buffer == [97, 98, 0]);
4095     assert(index == 1);
4096 
4097     buffer.write!char('b', &index);
4098     assert(buffer == [97, 98, 0]);
4099     assert(index == 2);
4100 
4101     buffer.write!char('c', &index);
4102     assert(buffer == [97, 98, 99]);
4103     assert(index == 3);
4104 }
4105 
4106 /// wchar (16bit - 2x ubyte)
4107 @system unittest
4108 {
4109     ubyte[] buffer = [0, 0, 0, 0];
4110 
4111     buffer.write!wchar('ą', 0);
4112     assert(buffer == [1, 5, 0, 0]);
4113 
4114     buffer.write!wchar('”', 2);
4115     assert(buffer == [1, 5, 32, 29]);
4116 
4117     size_t index = 0;
4118     buffer.write!wchar('ć', &index);
4119     assert(buffer == [1, 7, 32, 29]);
4120     assert(index == 2);
4121 
4122     buffer.write!wchar('ą', &index);
4123     assert(buffer == [1, 7, 1, 5]);
4124     assert(index == 4);
4125 }
4126 
4127 /// dchar (32bit - 4x ubyte)
4128 @system unittest
4129 {
4130     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4131 
4132     buffer.write!dchar('ą', 0);
4133     assert(buffer == [0, 0, 1, 5, 0, 0, 0, 0]);
4134 
4135     buffer.write!dchar('”', 4);
4136     assert(buffer == [0, 0, 1, 5, 0, 0, 32, 29]);
4137 
4138     size_t index = 0;
4139     buffer.write!dchar('ć', &index);
4140     assert(buffer == [0, 0, 1, 7, 0, 0, 32, 29]);
4141     assert(index == 4);
4142 
4143     buffer.write!dchar('ą', &index);
4144     assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
4145     assert(index == 8);
4146 }
4147 
4148 /// float (32bit - 4x ubyte)
4149 @system unittest
4150 {
4151     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4152 
4153     buffer.write!float(32.0f, 0);
4154     assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
4155 
4156     buffer.write!float(25.0f, 4);
4157     assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
4158 
4159     size_t index = 0;
4160     buffer.write!float(25.0f, &index);
4161     assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4162     assert(index == 4);
4163 
4164     buffer.write!float(32.0f, &index);
4165     assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4166     assert(index == 8);
4167 }
4168 
4169 /// double (64bit - 8x ubyte)
4170 @system unittest
4171 {
4172     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4173 
4174     buffer.write!double(32.0, 0);
4175     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4176 
4177     buffer.write!double(25.0, 8);
4178     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4179 
4180     size_t index = 0;
4181     buffer.write!double(25.0, &index);
4182     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4183     assert(index == 8);
4184 
4185     buffer.write!double(32.0, &index);
4186     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4187     assert(index == 16);
4188 }
4189 
4190 /// enum
4191 @system unittest
4192 {
4193     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4194 
4195     enum Foo
4196     {
4197         one = 10,
4198         two = 20,
4199         three = 30
4200     }
4201 
4202     buffer.write!Foo(Foo.one, 0);
4203     assert(buffer == [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0]);
4204 
4205     buffer.write!Foo(Foo.two, 4);
4206     assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0]);
4207 
4208     buffer.write!Foo(Foo.three, 8);
4209     assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4210 
4211     size_t index = 0;
4212     buffer.write!Foo(Foo.three, &index);
4213     assert(buffer == [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30]);
4214     assert(index == 4);
4215 
4216     buffer.write!Foo(Foo.one, &index);
4217     assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30]);
4218     assert(index == 8);
4219 
4220     buffer.write!Foo(Foo.two, &index);
4221     assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
4222     assert(index == 12);
4223 }
4224 
4225 // enum - bool
4226 @system unittest
4227 {
4228     ubyte[] buffer = [0, 0];
4229 
4230     enum Bool: bool
4231     {
4232         bfalse = false,
4233         btrue = true,
4234     }
4235 
4236     buffer.write!Bool(Bool.btrue, 0);
4237     assert(buffer == [1, 0]);
4238 
4239     buffer.write!Bool(Bool.btrue, 1);
4240     assert(buffer == [1, 1]);
4241 
4242     size_t index = 0;
4243     buffer.write!Bool(Bool.bfalse, &index);
4244     assert(buffer == [0, 1]);
4245     assert(index == 1);
4246 
4247     buffer.write!Bool(Bool.bfalse, &index);
4248     assert(buffer == [0, 0]);
4249     assert(index == 2);
4250 }
4251 
4252 /// enum - float
4253 @system unittest
4254 {
4255     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4256 
4257     enum Float: float
4258     {
4259         one = 32.0f,
4260         two = 25.0f
4261     }
4262 
4263     buffer.write!Float(Float.one, 0);
4264     assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
4265 
4266     buffer.write!Float(Float.two, 4);
4267     assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
4268 
4269     size_t index = 0;
4270     buffer.write!Float(Float.two, &index);
4271     assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4272     assert(index == 4);
4273 
4274     buffer.write!Float(Float.one, &index);
4275     assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4276     assert(index == 8);
4277 }
4278 
4279 /// enum - double
4280 @system unittest
4281 {
4282     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4283 
4284     enum Double: double
4285     {
4286         one = 32.0,
4287         two = 25.0
4288     }
4289 
4290     buffer.write!Double(Double.one, 0);
4291     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4292 
4293     buffer.write!Double(Double.two, 8);
4294     assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4295 
4296     size_t index = 0;
4297     buffer.write!Double(Double.two, &index);
4298     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4299     assert(index == 8);
4300 
4301     buffer.write!Double(Double.one, &index);
4302     assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4303     assert(index == 16);
4304 }
4305 
4306 /// enum - real
4307 @system unittest
4308 {
4309     ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4310 
4311     enum Real: real
4312     {
4313         one = 32.0,
4314         two = 25.0
4315     }
4316 
4317     static assert(!__traits(compiles, buffer.write!Real(Real.one)));
4318 }
4319 
4320 
4321 /++
4322     Takes an integral value, converts it to the given endianness, and appends
4323     it to the given range of `ubyte`s (using `put`) as a sequence of
4324     `T.sizeof` `ubyte`s starting at index. `hasSlicing!R` must be
4325     `true`.
4326 
4327     Params:
4328         T     = The integral type to convert the first `T.sizeof` bytes to.
4329         endianness = The endianness to write the bytes in.
4330         range = The range to _append to.
4331         value = The value to _append.
4332   +/
4333 void append(T, Endian endianness = Endian.bigEndian, R)(R range, const T value)
4334 if (canSwapEndianness!T && isOutputRange!(R, ubyte))
4335 {
4336     static if (endianness == Endian.bigEndian)
4337         immutable bytes = nativeToBigEndian!T(value);
4338     else
4339         immutable bytes = nativeToLittleEndian!T(value);
4340 
4341     put(range, bytes[]);
4342 }
4343 
4344 ///
4345 @safe unittest
4346 {
4347     import std.array;
4348     auto buffer = appender!(const ubyte[])();
4349     buffer.append!ushort(261);
4350     assert(buffer.data == [1, 5]);
4351 
4352     buffer.append!uint(369700095u);
4353     assert(buffer.data == [1, 5, 22, 9, 44, 255]);
4354 
4355     buffer.append!ubyte(8);
4356     assert(buffer.data == [1, 5, 22, 9, 44, 255, 8]);
4357 }
4358 
4359 /// bool
4360 @safe unittest
4361 {
4362     import std.array : appender;
4363     auto buffer = appender!(const ubyte[])();
4364 
4365     buffer.append!bool(true);
4366     assert(buffer.data == [1]);
4367 
4368     buffer.append!bool(false);
4369     assert(buffer.data == [1, 0]);
4370 }
4371 
4372 /// char wchar dchar
4373 @safe unittest
4374 {
4375     import std.array : appender;
4376     auto buffer = appender!(const ubyte[])();
4377 
4378     buffer.append!char('a');
4379     assert(buffer.data == [97]);
4380 
4381     buffer.append!char('b');
4382     assert(buffer.data == [97, 98]);
4383 
4384     buffer.append!wchar('ą');
4385     assert(buffer.data == [97, 98, 1, 5]);
4386 
4387     buffer.append!dchar('ą');
4388         assert(buffer.data == [97, 98, 1, 5, 0, 0, 1, 5]);
4389 }
4390 
4391 /// float double
4392 @safe unittest
4393 {
4394     import std.array : appender;
4395     auto buffer = appender!(const ubyte[])();
4396 
4397     buffer.append!float(32.0f);
4398     assert(buffer.data == [66, 0, 0, 0]);
4399 
4400     buffer.append!double(32.0);
4401     assert(buffer.data == [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4402 }
4403 
4404 /// enum
4405 @safe unittest
4406 {
4407     import std.array : appender;
4408     auto buffer = appender!(const ubyte[])();
4409 
4410     enum Foo
4411     {
4412         one = 10,
4413         two = 20,
4414         three = 30
4415     }
4416 
4417     buffer.append!Foo(Foo.one);
4418     assert(buffer.data == [0, 0, 0, 10]);
4419 
4420     buffer.append!Foo(Foo.two);
4421     assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20]);
4422 
4423     buffer.append!Foo(Foo.three);
4424     assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4425 }
4426 
4427 /// enum - bool
4428 @safe unittest
4429 {
4430     import std.array : appender;
4431     auto buffer = appender!(const ubyte[])();
4432 
4433     enum Bool: bool
4434     {
4435         bfalse = false,
4436         btrue = true,
4437     }
4438 
4439     buffer.append!Bool(Bool.btrue);
4440     assert(buffer.data == [1]);
4441 
4442     buffer.append!Bool(Bool.bfalse);
4443     assert(buffer.data == [1, 0]);
4444 
4445     buffer.append!Bool(Bool.btrue);
4446     assert(buffer.data == [1, 0, 1]);
4447 }
4448 
4449 /// enum - float
4450 @safe unittest
4451 {
4452     import std.array : appender;
4453     auto buffer = appender!(const ubyte[])();
4454 
4455     enum Float: float
4456     {
4457         one = 32.0f,
4458         two = 25.0f
4459     }
4460 
4461     buffer.append!Float(Float.one);
4462     assert(buffer.data == [66, 0, 0, 0]);
4463 
4464     buffer.append!Float(Float.two);
4465     assert(buffer.data == [66, 0, 0, 0, 65, 200, 0, 0]);
4466 }
4467 
4468 /// enum - double
4469 @safe unittest
4470 {
4471     import std.array : appender;
4472     auto buffer = appender!(const ubyte[])();
4473 
4474     enum Double: double
4475     {
4476         one = 32.0,
4477         two = 25.0
4478     }
4479 
4480     buffer.append!Double(Double.one);
4481     assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0]);
4482 
4483     buffer.append!Double(Double.two);
4484     assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4485 }
4486 
4487 /// enum - real
4488 @safe unittest
4489 {
4490     import std.array : appender;
4491     auto buffer = appender!(const ubyte[])();
4492 
4493     enum Real: real
4494     {
4495         one = 32.0,
4496         two = 25.0
4497     }
4498 
4499     static assert(!__traits(compiles, buffer.append!Real(Real.one)));
4500 }
4501 
4502 @system unittest
4503 {
4504     import std.array;
4505     import std.format : format;
4506     import std.meta : AliasSeq;
4507     static foreach (endianness; [Endian.bigEndian, Endian.littleEndian])
4508     {{
4509         auto toWrite = appender!(ubyte[])();
4510         alias Types = AliasSeq!(uint, int, long, ulong, short, ubyte, ushort, byte, uint);
4511         ulong[] values = [42, -11, long.max, 1098911981329L, 16, 255, 19012, 2, 17];
4512         assert(Types.length == values.length);
4513 
4514         size_t index = 0;
4515         size_t length = 0;
4516         static foreach (T; Types)
4517         {
4518             toWrite.append!(T, endianness)(cast(T) values[index++]);
4519             length += T.sizeof;
4520         }
4521 
4522         auto toRead = toWrite.data;
4523         assert(toRead.length == length);
4524 
4525         index = 0;
4526         static foreach (T; Types)
4527         {
4528             assert(toRead.peek!(T, endianness)() == values[index], format("Failed Index: %s", index));
4529             assert(toRead.peek!(T, endianness)(0) == values[index], format("Failed Index: %s", index));
4530             assert(toRead.length == length,
4531                    format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4532             assert(toRead.read!(T, endianness)() == values[index], format("Failed Index: %s", index));
4533             length -= T.sizeof;
4534             assert(toRead.length == length,
4535                    format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4536             ++index;
4537         }
4538         assert(toRead.empty);
4539     }}
4540 }
4541 
4542 /**
4543 Counts the number of set bits in the binary representation of `value`.
4544 For signed integers, the sign bit is included in the count.
4545 */
4546 private uint countBitsSet(T)(const T value)
4547 if (isIntegral!T)
4548 {
4549     static if (T.sizeof == 8)
4550     {
4551         import core.bitop : popcnt;
4552         const c = popcnt(cast(ulong) value);
4553     }
4554     else static if (T.sizeof == 4)
4555     {
4556         import core.bitop : popcnt;
4557         const c = popcnt(cast(uint) value);
4558     }
4559     // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
4560     else static if (T.sizeof == 2)
4561     {
4562         uint c = value - ((value >> 1) & 0x5555);
4563         c = ((c >> 2) & 0x3333) + (c & 0X3333);
4564         c = ((c >> 4) + c) & 0x0F0F;
4565         c = ((c >> 8) + c) & 0x00FF;
4566     }
4567     else static if (T.sizeof == 1)
4568     {
4569         uint c = value - ((value >> 1) & 0x55);
4570         c = ((c >> 2) & 0x33) + (c & 0X33);
4571         c = ((c >> 4) + c) & 0x0F;
4572     }
4573     else
4574     {
4575         static assert(false, "countBitsSet only supports 1, 2, 4, or 8 byte sized integers.");
4576     }
4577     return cast(uint) c;
4578 }
4579 
4580 @safe unittest
4581 {
4582     assert(countBitsSet(1) == 1);
4583     assert(countBitsSet(0) == 0);
4584     assert(countBitsSet(int.min) == 1);
4585     assert(countBitsSet(uint.max) == 32);
4586 }
4587 
4588 @safe unittest
4589 {
4590     import std.meta;
4591     static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
4592     {
4593         assert(countBitsSet(cast(T) 0) == 0);
4594         assert(countBitsSet(cast(T) 1) == 1);
4595         assert(countBitsSet(cast(T) 2) == 1);
4596         assert(countBitsSet(cast(T) 3) == 2);
4597         assert(countBitsSet(cast(T) 4) == 1);
4598         assert(countBitsSet(cast(T) 5) == 2);
4599         assert(countBitsSet(cast(T) 127) == 7);
4600         static if (isSigned!T)
4601         {
4602             assert(countBitsSet(cast(T)-1) == 8 * T.sizeof);
4603             assert(countBitsSet(T.min) == 1);
4604         }
4605         else
4606         {
4607             assert(countBitsSet(T.max) == 8 * T.sizeof);
4608         }
4609         // Check CTFE compiles.
4610         static assert(countBitsSet(cast(T) 1) == 1);
4611     }
4612     assert(countBitsSet(1_000_000) == 7);
4613     foreach (i; 0 .. 63)
4614         assert(countBitsSet(1UL << i) == 1);
4615 }
4616 
4617 private struct BitsSet(T)
4618 {
4619     static assert(T.sizeof <= 8, "bitsSet assumes T is no more than 64-bit.");
4620 
4621 @nogc pure nothrow:
4622 
4623     this(T value, size_t startIndex = 0)
4624     {
4625         _value = value;
4626         // Further calculation is only valid and needed when the range is non-empty.
4627         if (!_value)
4628             return;
4629 
4630         import core.bitop : bsf;
4631         immutable trailingZerosCount = bsf(value);
4632         _value >>>= trailingZerosCount;
4633         _index = startIndex + trailingZerosCount;
4634     }
4635 
4636     @property size_t front() const
4637     {
4638         return _index;
4639     }
4640 
4641     @property bool empty() const
4642     {
4643         return !_value;
4644     }
4645 
4646     void popFront()
4647     {
4648         assert(_value, "Cannot call popFront on empty range.");
4649 
4650         _value >>>= 1;
4651         // Further calculation is only valid and needed when the range is non-empty.
4652         if (!_value)
4653             return;
4654 
4655         import core.bitop : bsf;
4656         immutable trailingZerosCount = bsf(_value);
4657         _value >>>= trailingZerosCount;
4658         _index += trailingZerosCount + 1;
4659     }
4660 
4661     @property BitsSet save() const
4662     {
4663         return this;
4664     }
4665 
4666     @property size_t length() const
4667     {
4668         return countBitsSet(_value);
4669     }
4670 
4671     private T _value;
4672     private size_t _index;
4673 }
4674 
4675 /**
4676 Range that iterates the indices of the set bits in `value`.
4677 Index 0 corresponds to the least significant bit.
4678 For signed integers, the highest index corresponds to the sign bit.
4679 */
4680 auto bitsSet(T)(const T value) @nogc pure nothrow
4681 if (isIntegral!T)
4682 {
4683     return BitsSet!T(value);
4684 }
4685 
4686 ///
4687 @safe unittest
4688 {
4689     import std.algorithm.comparison : equal;
4690     import std.range : iota;
4691 
4692     assert(bitsSet(1).equal([0]));
4693     assert(bitsSet(5).equal([0, 2]));
4694     assert(bitsSet(-1).equal(iota(32)));
4695     assert(bitsSet(int.min).equal([31]));
4696 }
4697 
4698 @safe unittest
4699 {
4700     import std.algorithm.comparison : equal;
4701     import std.range : iota;
4702 
4703     import std.meta;
4704     static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
4705     {
4706         assert(bitsSet(cast(T) 0).empty);
4707         assert(bitsSet(cast(T) 1).equal([0]));
4708         assert(bitsSet(cast(T) 2).equal([1]));
4709         assert(bitsSet(cast(T) 3).equal([0, 1]));
4710         assert(bitsSet(cast(T) 4).equal([2]));
4711         assert(bitsSet(cast(T) 5).equal([0, 2]));
4712         assert(bitsSet(cast(T) 127).equal(iota(7)));
4713         static if (isSigned!T)
4714         {
4715             assert(bitsSet(cast(T)-1).equal(iota(8 * T.sizeof)));
4716             assert(bitsSet(T.min).equal([8 * T.sizeof - 1]));
4717         }
4718         else
4719         {
4720             assert(bitsSet(T.max).equal(iota(8 * T.sizeof)));
4721         }
4722     }
4723     assert(bitsSet(1_000_000).equal([6, 9, 14, 16, 17, 18, 19]));
4724     foreach (i; 0 .. 63)
4725         assert(bitsSet(1UL << i).equal([i]));
4726 }