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