The OpenD Programming Language

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