1 // Written in the D programming language.
2 
3 /**
4 A one-stop shop for converting values from one type to another.
5 
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(BOOKTABLE,
8 $(TR $(TH Category) $(TH Functions))
9 $(TR $(TD Generic) $(TD
10         $(LREF asOriginalType)
11         $(LREF castFrom)
12         $(LREF emplace)
13         $(LREF parse)
14         $(LREF to)
15         $(LREF toChars)
16 ))
17 $(TR $(TD Strings) $(TD
18         $(LREF text)
19         $(LREF wtext)
20         $(LREF dtext)
21         $(LREF hexString)
22 ))
23 $(TR $(TD Numeric) $(TD
24         $(LREF octal)
25         $(LREF roundTo)
26         $(LREF signed)
27         $(LREF unsigned)
28 ))
29 $(TR $(TD Exceptions) $(TD
30         $(LREF ConvException)
31         $(LREF ConvOverflowException)
32 ))
33 )
34 
35 Copyright: Copyright Digital Mars 2007-.
36 
37 License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
38 
39 Authors:   $(HTTP digitalmars.com, Walter Bright),
40            $(HTTP erdani.org, Andrei Alexandrescu),
41            Shin Fujishiro,
42            Adam D. Ruppe,
43            Kenji Hara
44 
45 Source:    $(PHOBOSSRC std/_conv.d)
46 
47 */
48 module std.conv;
49 
50 public import std.ascii : LetterCase;
51 
52 import std.meta;
53 import std.range.primitives;
54 import std.traits;
55 
56 // Same as std.string.format, but "self-importing".
57 // Helps reduce code and imports, particularly in static asserts.
58 // Also helps with missing imports errors.
convFormat()59 package template convFormat()
60 {
61     import std.format : format;
62     alias convFormat = format;
63 }
64 
65 /* ************* Exceptions *************** */
66 
67 /**
68  * Thrown on conversion errors.
69  */
70 class ConvException : Exception
71 {
72     import std.exception : basicExceptionCtors;
73     ///
74     mixin basicExceptionCtors;
75 }
76 
convError(S,T)77 private auto convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE__)
78 {
79     string msg;
80 
81     if (source.empty)
82         msg = "Unexpected end of input when converting from type " ~ S.stringof ~ " to type " ~ T.stringof;
83     else
84     {
85         ElementType!S el = source.front;
86 
87         if (el == '\n')
88             msg = text("Unexpected '\\n' when converting from type " ~ S.stringof ~ " to type " ~ T.stringof);
89         else
90             msg =  text("Unexpected '", el,
91                  "' when converting from type " ~ S.stringof ~ " to type " ~ T.stringof);
92     }
93 
94     return new ConvException(msg, fn, ln);
95 }
96 
convError(S,T)97 private auto convError(S, T)(S source, int radix, string fn = __FILE__, size_t ln = __LINE__)
98 {
99     string msg;
100 
101     if (source.empty)
102         msg = text("Unexpected end of input when converting from type " ~ S.stringof ~ " base ", radix,
103                 " to type " ~ T.stringof);
104     else
105         msg = text("Unexpected '", source.front,
106             "' when converting from type " ~ S.stringof ~ " base ", radix,
107             " to type " ~ T.stringof);
108 
109     return new ConvException(msg, fn, ln);
110 }
111 
112 @safe pure/* nothrow*/  // lazy parameter bug
113 private auto parseError(lazy string msg, string fn = __FILE__, size_t ln = __LINE__)
114 {
115     return new ConvException(text("Can't parse string: ", msg), fn, ln);
116 }
117 
parseCheck(alias source)118 private void parseCheck(alias source)(dchar c, string fn = __FILE__, size_t ln = __LINE__)
119 {
120     if (source.empty)
121         throw parseError(text("unexpected end of input when expecting", "\"", c, "\""));
122     if (source.front != c)
123         throw parseError(text("\"", c, "\" is missing"), fn, ln);
124     source.popFront();
125 }
126 
127 private
128 {
129     T toStr(T, S)(S src)
130     if (isSomeString!T)
131     {
132         // workaround for Bugzilla 14198
133         static if (is(S == bool) && is(typeof({ T s = "string"; })))
134         {
135             return src ? "true" : "false";
136         }
137         else
138         {
139             import std.array : appender;
140             import std.format : FormatSpec, formatValue;
141 
142             auto w = appender!T();
143             FormatSpec!(ElementEncodingType!T) f;
144             formatValue(w, src, f);
145             return w.data;
146         }
147     }
148 
isExactSomeString(T)149     template isExactSomeString(T)
150     {
151         enum isExactSomeString = isSomeString!T && !is(T == enum);
152     }
153 
isEnumStrToStr(S,T)154     template isEnumStrToStr(S, T)
155     {
156         enum isEnumStrToStr = isImplicitlyConvertible!(S, T) &&
157                               is(S == enum) && isExactSomeString!T;
158     }
isNullToStr(S,T)159     template isNullToStr(S, T)
160     {
161         enum isNullToStr = isImplicitlyConvertible!(S, T) &&
162                            (is(Unqual!S == typeof(null))) && isExactSomeString!T;
163     }
164 }
165 
166 /**
167  * Thrown on conversion overflow errors.
168  */
169 class ConvOverflowException : ConvException
170 {
171     @safe pure nothrow
172     this(string s, string fn = __FILE__, size_t ln = __LINE__)
173     {
174         super(s, fn, ln);
175     }
176 }
177 
178 /**
179 The `to` template converts a value from one type _to another.
180 The source type is deduced and the target type must be specified, for example the
181 expression `to!int(42.0)` converts the number 42 from
182 `double` _to `int`. The conversion is "safe", i.e.,
183 it checks for overflow; `to!int(4.2e10)` would throw the
184 `ConvOverflowException` exception. Overflow checks are only
185 inserted when necessary, e.g., `to!double(42)` does not do
186 any checking because any `int` fits in a `double`.
187 
188 Conversions from string _to numeric types differ from the C equivalents
189 `atoi()` and `atol()` by checking for overflow and not allowing whitespace.
190 
191 For conversion of strings _to signed types, the grammar recognized is:
192 $(PRE $(I Integer): $(I Sign UnsignedInteger)
193 $(I UnsignedInteger)
194 $(I Sign):
195     $(B +)
196     $(B -))
197 
198 For conversion _to unsigned types, the grammar recognized is:
199 $(PRE $(I UnsignedInteger):
200     $(I DecimalDigit)
201     $(I DecimalDigit) $(I UnsignedInteger))
202  */
to(T)203 template to(T)
204 {
205     T to(A...)(A args)
206         if (A.length > 0)
207     {
208         return toImpl!T(args);
209     }
210 
211     // Fix issue 6175
212     T to(S)(ref S arg)
213         if (isStaticArray!S)
214     {
215         return toImpl!T(arg);
216     }
217 
218     // Fix issue 16108
219     T to(S)(ref S arg)
220         if (isAggregateType!S && !isCopyable!S)
221     {
222         return toImpl!T(arg);
223     }
224 }
225 
226 /**
227  * Converting a value _to its own type (useful mostly for generic code)
228  * simply returns its argument.
229  */
230 @safe pure unittest
231 {
232     int a = 42;
233     int b = to!int(a);
234     double c = to!double(3.14); // c is double with value 3.14
235 }
236 
237 /**
238  * Converting among numeric types is a safe way _to cast them around.
239  *
240  * Conversions from floating-point types _to integral types allow loss of
241  * precision (the fractional part of a floating-point number). The
242  * conversion is truncating towards zero, the same way a cast would
243  * truncate. (_To round a floating point value when casting _to an
244  * integral, use `roundTo`.)
245  */
246 @safe pure unittest
247 {
248     import std.exception : assertThrown;
249 
250     int a = 420;
251     assert(to!long(a) == a);
252     assertThrown!ConvOverflowException(to!byte(a));
253 
254     assert(to!int(4.2e6) == 4200000);
255     assertThrown!ConvOverflowException(to!uint(-3.14));
256     assert(to!uint(3.14) == 3);
257     assert(to!uint(3.99) == 3);
258     assert(to!int(-3.99) == -3);
259 }
260 
261 /**
262  * When converting strings _to numeric types, note that the D hexadecimal and binary
263  * literals are not handled. Neither the prefixes that indicate the base, nor the
264  * horizontal bar used _to separate groups of digits are recognized. This also
265  * applies to the suffixes that indicate the type.
266  *
267  * _To work around this, you can specify a radix for conversions involving numbers.
268  */
269 @safe pure unittest
270 {
271     auto str = to!string(42, 16);
272     assert(str == "2A");
273     auto i = to!int(str, 16);
274     assert(i == 42);
275 }
276 
277 /**
278  * Conversions from integral types _to floating-point types always
279  * succeed, but might lose accuracy. The largest integers with a
280  * predecessor representable in floating-point format are `2^24-1` for
281  * `float`, `2^53-1` for `double`, and `2^64-1` for `real` (when
282  * `real` is 80-bit, e.g. on Intel machines).
283  */
284 @safe pure unittest
285 {
286     // 2^24 - 1, largest proper integer representable as float
287     int a = 16_777_215;
288     assert(to!int(to!float(a)) == a);
289     assert(to!int(to!float(-a)) == -a);
290 }
291 
292 /**
293  * Converting an array _to another array type works by converting each
294  * element in turn. Associative arrays can be converted _to associative
295  * arrays as long as keys and values can in turn be converted.
296  */
297 @safe pure unittest
298 {
299     import std.string : split;
300 
301     int[] a = [1, 2, 3];
302     auto b = to!(float[])(a);
303     assert(b == [1.0f, 2, 3]);
304     string str = "1 2 3 4 5 6";
305     auto numbers = to!(double[])(split(str));
306     assert(numbers == [1.0, 2, 3, 4, 5, 6]);
307     int[string] c;
308     c["a"] = 1;
309     c["b"] = 2;
310     auto d = to!(double[wstring])(c);
311     assert(d["a"w] == 1 && d["b"w] == 2);
312 }
313 
314 /**
315  * Conversions operate transitively, meaning that they work on arrays and
316  * associative arrays of any complexity.
317  *
318  * This conversion works because `to!short` applies _to an `int`, `to!wstring`
319  * applies _to a `string`, `to!string` applies _to a `double`, and
320  * `to!(double[])` applies _to an `int[]`. The conversion might throw an
321  * exception because `to!short` might fail the range check.
322  */
323 @safe unittest
324 {
325     int[string][double[int[]]] a;
326     auto b = to!(short[wstring][string[double[]]])(a);
327 }
328 
329 /**
330  * Object-to-object conversions by dynamic casting throw exception when
331  * the source is non-null and the target is null.
332  */
333 @safe pure unittest
334 {
335     import std.exception : assertThrown;
336     // Testing object conversions
337     class A {}
338     class B : A {}
339     class C : A {}
340     A a1 = new A, a2 = new B, a3 = new C;
341     assert(to!B(a2) is a2);
342     assert(to!C(a3) is a3);
343     assertThrown!ConvException(to!B(a3));
344 }
345 
346 /**
347  * Stringize conversion from all types is supported.
348  * $(UL
349  *   $(LI String _to string conversion works for any two string types having
350  *        ($(D char), $(D wchar), $(D dchar)) character widths and any
351  *        combination of qualifiers (mutable, $(D const), or $(D immutable)).)
352  *   $(LI Converts array (other than strings) _to string.
353  *        Each element is converted by calling $(D to!T).)
354  *   $(LI Associative array _to string conversion.
355  *        Each element is printed by calling $(D to!T).)
356  *   $(LI Object _to string conversion calls $(D toString) against the object or
357  *        returns $(D "null") if the object is null.)
358  *   $(LI Struct _to string conversion calls $(D toString) against the struct if
359  *        it is defined.)
360  *   $(LI For structs that do not define $(D toString), the conversion _to string
361  *        produces the list of fields.)
362  *   $(LI Enumerated types are converted _to strings as their symbolic names.)
363  *   $(LI Boolean values are printed as $(D "true") or $(D "false").)
364  *   $(LI $(D char), $(D wchar), $(D dchar) _to a string type.)
365  *   $(LI Unsigned or signed integers _to strings.
366  *        $(DL $(DT [special case])
367  *             $(DD Convert integral value _to string in $(D_PARAM radix) radix.
368  *             radix must be a value from 2 to 36.
369  *             value is treated as a signed value only if radix is 10.
370  *             The characters A through Z are used to represent values 10 through 36
371  *             and their case is determined by the $(D_PARAM letterCase) parameter.)))
372  *   $(LI All floating point types _to all string types.)
373  *   $(LI Pointer to string conversions prints the pointer as a $(D size_t) value.
374  *        If pointer is $(D char*), treat it as C-style strings.
375  *        In that case, this function is $(D @system).))
376  */
377 @system pure unittest // @system due to cast and ptr
378 {
379     // Conversion representing dynamic/static array with string
380     long[] a = [ 1, 3, 5 ];
381     assert(to!string(a) == "[1, 3, 5]");
382 
383     // Conversion representing associative array with string
384     int[string] associativeArray = ["0":1, "1":2];
385     assert(to!string(associativeArray) == `["0":1, "1":2]` ||
386            to!string(associativeArray) == `["1":2, "0":1]`);
387 
388     // char* to string conversion
389     assert(to!string(cast(char*) null) == "");
390     assert(to!string("foo\0".ptr) == "foo");
391 
392     // Conversion reinterpreting void array to string
393     auto w = "abcx"w;
394     const(void)[] b = w;
395     assert(b.length == 8);
396 
397     auto c = to!(wchar[])(b);
398     assert(c == "abcx");
399 }
400 
401 // Tests for issue 6175
402 @safe pure nothrow unittest
403 {
404     char[9] sarr = "blablabla";
405     auto darr = to!(char[])(sarr);
406     assert(sarr.ptr == darr.ptr);
407     assert(sarr.length == darr.length);
408 }
409 
410 // Tests for issue 7348
411 @safe pure /+nothrow+/ unittest
412 {
413     assert(to!string(null) == "null");
414     assert(text(null) == "null");
415 }
416 
417 // Tests for issue 11390
418 @safe pure /+nothrow+/ unittest
419 {
420     const(typeof(null)) ctn;
421     immutable(typeof(null)) itn;
422     assert(to!string(ctn) == "null");
423     assert(to!string(itn) == "null");
424 }
425 
426 // Tests for issue 8729: do NOT skip leading WS
427 @safe pure unittest
428 {
429     import std.exception;
430     foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
431     {
432         assertThrown!ConvException(to!T(" 0"));
433         assertThrown!ConvException(to!T(" 0", 8));
434     }
435     foreach (T; AliasSeq!(float, double, real))
436     {
437         assertThrown!ConvException(to!T(" 0"));
438     }
439 
440     assertThrown!ConvException(to!bool(" true"));
441 
442     alias NullType = typeof(null);
443     assertThrown!ConvException(to!NullType(" null"));
444 
445     alias ARR = int[];
446     assertThrown!ConvException(to!ARR(" [1]"));
447 
448     alias AA = int[int];
449     assertThrown!ConvException(to!AA(" [1:1]"));
450 }
451 
452 /**
453 If the source type is implicitly convertible to the target type, $(D
454 to) simply performs the implicit conversion.
455  */
456 private T toImpl(T, S)(S value)
457 if (isImplicitlyConvertible!(S, T) &&
458     !isEnumStrToStr!(S, T) && !isNullToStr!(S, T))
459 {
isSignedInt(T)460     template isSignedInt(T)
461     {
462         enum isSignedInt = isIntegral!T && isSigned!T;
463     }
464     alias isUnsignedInt = isUnsigned;
465 
466     // Conversion from integer to integer, and changing its sign
467     static if (isUnsignedInt!S && isSignedInt!T && S.sizeof == T.sizeof)
468     {   // unsigned to signed & same size
469         import std.exception : enforce;
470         enforce(value <= cast(S) T.max,
471                 new ConvOverflowException("Conversion positive overflow"));
472     }
473     else static if (isSignedInt!S && isUnsignedInt!T)
474     {   // signed to unsigned
475         import std.exception : enforce;
476         enforce(0 <= value,
477                 new ConvOverflowException("Conversion negative overflow"));
478     }
479 
480     return value;
481 }
482 
483 @safe pure nothrow unittest
484 {
485     enum E { a }  // Issue 9523 - Allow identity enum conversion
486     auto e = to!E(E.a);
487     assert(e == E.a);
488 }
489 
490 @safe pure nothrow unittest
491 {
492     int a = 42;
493     auto b = to!long(a);
494     assert(a == b);
495 }
496 
497 // Tests for issue 6377
498 @safe pure unittest
499 {
500     import std.exception;
501     // Conversion between same size
502     foreach (S; AliasSeq!(byte, short, int, long))
503     (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
504         alias U = Unsigned!S;
505 
506         foreach (Sint; AliasSeq!(S, const S, immutable S))
507         foreach (Uint; AliasSeq!(U, const U, immutable U))
508         {
509             // positive overflow
510             Uint un = Uint.max;
511             assertThrown!ConvOverflowException(to!Sint(un),
512                 text(Sint.stringof, ' ', Uint.stringof, ' ', un));
513 
514             // negative overflow
515             Sint sn = -1;
516             assertThrown!ConvOverflowException(to!Uint(sn),
517                 text(Sint.stringof, ' ', Uint.stringof, ' ', un));
518         }
519     }();
520 
521     // Conversion between different size
522     foreach (i, S1; AliasSeq!(byte, short, int, long))
523     foreach (   S2; AliasSeq!(byte, short, int, long)[i+1..$])
524     (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
525         alias U1 = Unsigned!S1;
526         alias U2 = Unsigned!S2;
527 
528         static assert(U1.sizeof < S2.sizeof);
529 
530         // small unsigned to big signed
531         foreach (Uint; AliasSeq!(U1, const U1, immutable U1))
532         foreach (Sint; AliasSeq!(S2, const S2, immutable S2))
533         {
534             Uint un = Uint.max;
535             assertNotThrown(to!Sint(un));
536             assert(to!Sint(un) == un);
537         }
538 
539         // big unsigned to small signed
540         foreach (Uint; AliasSeq!(U2, const U2, immutable U2))
541         foreach (Sint; AliasSeq!(S1, const S1, immutable S1))
542         {
543             Uint un = Uint.max;
544             assertThrown(to!Sint(un));
545         }
546 
547         static assert(S1.sizeof < U2.sizeof);
548 
549         // small signed to big unsigned
550         foreach (Sint; AliasSeq!(S1, const S1, immutable S1))
551         foreach (Uint; AliasSeq!(U2, const U2, immutable U2))
552         {
553             Sint sn = -1;
554             assertThrown!ConvOverflowException(to!Uint(sn));
555         }
556 
557         // big signed to small unsigned
558         foreach (Sint; AliasSeq!(S2, const S2, immutable S2))
559         foreach (Uint; AliasSeq!(U1, const U1, immutable U1))
560         {
561             Sint sn = -1;
562             assertThrown!ConvOverflowException(to!Uint(sn));
563         }
564     }();
565 }
566 
567 /*
568   Converting static arrays forwards to their dynamic counterparts.
569  */
570 private T toImpl(T, S)(ref S s)
571 if (isStaticArray!S)
572 {
573     return toImpl!(T, typeof(s[0])[])(s);
574 }
575 
576 @safe pure nothrow unittest
577 {
578     char[4] test = ['a', 'b', 'c', 'd'];
579     static assert(!isInputRange!(Unqual!(char[4])));
580     assert(to!string(test) == test);
581 }
582 
583 /**
584 When source type supports member template function opCast, it is used.
585 */
586 private T toImpl(T, S)(S value)
587 if (!isImplicitlyConvertible!(S, T) &&
588     is(typeof(S.init.opCast!T()) : T) &&
589     !isExactSomeString!T &&
590     !is(typeof(T(value))))
591 {
592     return value.opCast!T();
593 }
594 
595 @safe pure unittest
596 {
597     static struct Test
598     {
599         struct T
600         {
thisTest::T601             this(S s) @safe pure { }
602         }
603         struct S
604         {
opCastTest605             T opCast(U)() @safe pure { assert(false); }
606         }
607     }
608     cast(void) to!(Test.T)(Test.S());
609 
610     // make sure std.conv.to is doing the same thing as initialization
611     Test.S s;
612     Test.T t = s;
613 }
614 
615 @safe pure unittest
616 {
617     class B
618     {
opCast(T)619         T opCast(T)() { return 43; }
620     }
621     auto b = new B;
622     assert(to!int(b) == 43);
623 
624     struct S
625     {
opCastS626         T opCast(T)() { return 43; }
627     }
628     auto s = S();
629     assert(to!int(s) == 43);
630 }
631 
632 /**
633 When target type supports 'converting construction', it is used.
634 $(UL $(LI If target type is struct, $(D T(value)) is used.)
635      $(LI If target type is class, $(D new T(value)) is used.))
636 */
637 private T toImpl(T, S)(S value)
638 if (!isImplicitlyConvertible!(S, T) &&
639     is(T == struct) && is(typeof(T(value))))
640 {
641     return T(value);
642 }
643 
644 // Bugzilla 3961
645 @safe pure unittest
646 {
647     struct Int
648     {
649         int x;
650     }
651     Int i = to!Int(1);
652 
653     static struct Int2
654     {
655         int x;
thisInt2656         this(int x) @safe pure { this.x = x; }
657     }
658     Int2 i2 = to!Int2(1);
659 
660     static struct Int3
661     {
662         int x;
opCallInt3663         static Int3 opCall(int x) @safe pure
664         {
665             Int3 i;
666             i.x = x;
667             return i;
668         }
669     }
670     Int3 i3 = to!Int3(1);
671 }
672 
673 // Bugzilla 6808
674 @safe pure unittest
675 {
676     static struct FakeBigInt
677     {
thisFakeBigInt678         this(string s) @safe pure {}
679     }
680 
681     string s = "101";
682     auto i3 = to!FakeBigInt(s);
683 }
684 
685 /// ditto
686 private T toImpl(T, S)(S value)
687 if (!isImplicitlyConvertible!(S, T) &&
688     is(T == class) && is(typeof(new T(value))))
689 {
690     return new T(value);
691 }
692 
693 @safe pure unittest
694 {
695     static struct S
696     {
697         int x;
698     }
699     static class C
700     {
701         int x;
this(int x)702         this(int x) @safe pure { this.x = x; }
703     }
704 
705     static class B
706     {
707         int value;
this(S src)708         this(S src) @safe pure { value = src.x; }
this(C src)709         this(C src) @safe pure { value = src.x; }
710     }
711 
712     S s = S(1);
713     auto b1 = to!B(s);  // == new B(s)
714     assert(b1.value == 1);
715 
716     C c = new C(2);
717     auto b2 = to!B(c);  // == new B(c)
718     assert(b2.value == 2);
719 
720     auto c2 = to!C(3);   // == new C(3)
721     assert(c2.x == 3);
722 }
723 
724 @safe pure unittest
725 {
726     struct S
727     {
728         class A
729         {
thisS730             this(B b) @safe pure {}
731         }
732         class B : A
733         {
thisS734             this() @safe pure { super(this); }
735         }
736     }
737 
738     S.B b = new S.B();
739     S.A a = to!(S.A)(b);      // == cast(S.A) b
740                               // (do not run construction conversion like new S.A(b))
741     assert(b is a);
742 
743     static class C : Object
744     {
this()745         this() @safe pure {}
this(Object o)746         this(Object o) @safe pure {}
747     }
748 
749     Object oc = new C();
750     C a2 = to!C(oc);    // == new C(a)
751                         // Construction conversion overrides down-casting conversion
752     assert(a2 !is a);   //
753 }
754 
755 /**
756 Object-to-object conversions by dynamic casting throw exception when the source is
757 non-null and the target is null.
758  */
759 private T toImpl(T, S)(S value)
760 if (!isImplicitlyConvertible!(S, T) &&
761     (is(S == class) || is(S == interface)) && !is(typeof(value.opCast!T()) : T) &&
762     (is(T == class) || is(T == interface)) && !is(typeof(new T(value))))
763 {
764     static if (is(T == immutable))
765     {
766             // immutable <- immutable
767             enum isModConvertible = is(S == immutable);
768     }
769     else static if (is(T == const))
770     {
771         static if (is(T == shared))
772         {
773             // shared const <- shared
774             // shared const <- shared const
775             // shared const <- immutable
776             enum isModConvertible = is(S == shared) || is(S == immutable);
777         }
778         else
779         {
780             // const <- mutable
781             // const <- immutable
782             enum isModConvertible = !is(S == shared);
783         }
784     }
785     else
786     {
787         static if (is(T == shared))
788         {
789             // shared <- shared mutable
790             enum isModConvertible = is(S == shared) && !is(S == const);
791         }
792         else
793         {
794             // (mutable) <- (mutable)
795             enum isModConvertible = is(Unqual!S == S);
796         }
797     }
798     static assert(isModConvertible, "Bad modifier conversion: "~S.stringof~" to "~T.stringof);
799 
800     auto result = ()@trusted{ return cast(T) value; }();
801     if (!result && value)
802     {
803         throw new ConvException("Cannot convert object of static type "
804                 ~S.classinfo.name~" and dynamic type "~value.classinfo.name
805                 ~" to type "~T.classinfo.name);
806     }
807     return result;
808 }
809 
810 // Unittest for 6288
811 @safe pure unittest
812 {
813     import std.exception;
814 
815     alias Identity(T)      =              T;
816     alias toConst(T)       =        const T;
817     alias toShared(T)      =       shared T;
818     alias toSharedConst(T) = shared const T;
819     alias toImmutable(T)   =    immutable T;
820     template AddModifier(int n)
821     if (0 <= n && n < 5)
822     {
823              static if (n == 0) alias AddModifier = Identity;
824         else static if (n == 1) alias AddModifier = toConst;
825         else static if (n == 2) alias AddModifier = toShared;
826         else static if (n == 3) alias AddModifier = toSharedConst;
827         else static if (n == 4) alias AddModifier = toImmutable;
828     }
829 
830     interface I {}
831     interface J {}
832 
833     class A {}
834     class B : A {}
835     class C : B, I, J {}
836     class D : I {}
837 
838     foreach (m1; AliasSeq!(0,1,2,3,4)) // enumerate modifiers
839     foreach (m2; AliasSeq!(0,1,2,3,4)) // ditto
840     (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
841         alias srcmod = AddModifier!m1;
842         alias tgtmod = AddModifier!m2;
843 
844         // Compile time convertible equals to modifier convertible.
845         static if (isImplicitlyConvertible!(srcmod!Object, tgtmod!Object))
846         {
847             // Test runtime conversions: class to class, class to interface,
848             // interface to class, and interface to interface
849 
850             // Check that the runtime conversion to succeed
851             srcmod!A ac = new srcmod!C();
852             srcmod!I ic = new srcmod!C();
853             assert(to!(tgtmod!C)(ac) !is null); // A(c) to C
854             assert(to!(tgtmod!I)(ac) !is null); // A(c) to I
855             assert(to!(tgtmod!C)(ic) !is null); // I(c) to C
856             assert(to!(tgtmod!J)(ic) !is null); // I(c) to J
857 
858             // Check that the runtime conversion fails
859             srcmod!A ab = new srcmod!B();
860             srcmod!I id = new srcmod!D();
861             assertThrown(to!(tgtmod!C)(ab));    // A(b) to C
862             assertThrown(to!(tgtmod!I)(ab));    // A(b) to I
863             assertThrown(to!(tgtmod!C)(id));    // I(d) to C
864             assertThrown(to!(tgtmod!J)(id));    // I(d) to J
865         }
866         else
867         {
868             // Check that the conversion is rejected statically
869             static assert(!is(typeof(to!(tgtmod!C)(srcmod!A.init))));   // A to C
870             static assert(!is(typeof(to!(tgtmod!I)(srcmod!A.init))));   // A to I
871             static assert(!is(typeof(to!(tgtmod!C)(srcmod!I.init))));   // I to C
872             static assert(!is(typeof(to!(tgtmod!J)(srcmod!I.init))));   // I to J
873         }
874     }();
875 }
876 
877 /**
878 Handles type _to string conversions
879 */
880 private T toImpl(T, S)(S value)
881 if (!(isImplicitlyConvertible!(S, T) &&
882     !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
883     !isInfinite!S && isExactSomeString!T)
884 {
885     static if (isExactSomeString!S && value[0].sizeof == ElementEncodingType!T.sizeof)
886     {
887         // string-to-string with incompatible qualifier conversion
888         static if (is(ElementEncodingType!T == immutable))
889         {
890             // conversion (mutable|const) -> immutable
891             return value.idup;
892         }
893         else
894         {
895             // conversion (immutable|const) -> mutable
896             return value.dup;
897         }
898     }
899     else static if (isExactSomeString!S)
900     {
901         import std.array : appender;
902         // other string-to-string
903         //Use Appender directly instead of toStr, which also uses a formatedWrite
904         auto w = appender!T();
905         w.put(value);
906         return w.data;
907     }
908     else static if (isIntegral!S && !is(S == enum))
909     {
910         // other integral-to-string conversions with default radix
911         return toImpl!(T, S)(value, 10);
912     }
913     else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[]))
914     {
915         import core.stdc.string : memcpy;
916         import std.exception : enforce;
917         // Converting void array to string
918         alias Char = Unqual!(ElementEncodingType!T);
919         auto raw = cast(const(ubyte)[]) value;
920         enforce(raw.length % Char.sizeof == 0,
921                 new ConvException("Alignment mismatch in converting a "
922                         ~ S.stringof ~ " to a "
923                         ~ T.stringof));
924         auto result = new Char[raw.length / Char.sizeof];
925         ()@trusted{ memcpy(result.ptr, value.ptr, value.length); }();
926         return cast(T) result;
927     }
928     else static if (isPointer!S && isSomeChar!(PointerTarget!S))
929     {
930         // This is unsafe because we cannot guarantee that the pointer is null terminated.
931         return () @system {
932             static if (is(S : const(char)*))
933                 import core.stdc.string : strlen;
934             else
935                 size_t strlen(S s) nothrow
936                 {
937                     S p = s;
938                     while (*p++) {}
939                     return p-s-1;
940                 }
941             return toImpl!T(value ? value[0 .. strlen(value)].dup : null);
942         }();
943     }
944     else static if (isSomeString!T && is(S == enum))
945     {
946         static if (isSwitchable!(OriginalType!S) && EnumMembers!S.length <= 50)
947         {
948             switch (value)
949             {
950                 foreach (member; NoDuplicates!(EnumMembers!S))
951                 {
952                     case member:
953                         return to!T(enumRep!(immutable(T), S, member));
954                 }
955                 default:
956             }
957         }
958         else
959         {
960             foreach (member; EnumMembers!S)
961             {
962                 if (value == member)
963                     return to!T(enumRep!(immutable(T), S, member));
964             }
965         }
966 
967         import std.array : appender;
968         import std.format : FormatSpec, formatValue;
969 
970         //Default case, delegate to format
971         //Note: we don't call toStr directly, to avoid duplicate work.
972         auto app = appender!T();
973         app.put("cast(" ~ S.stringof ~ ")");
974         FormatSpec!char f;
975         formatValue(app, cast(OriginalType!S) value, f);
976         return app.data;
977     }
978     else
979     {
980         // other non-string values runs formatting
981         return toStr!T(value);
982     }
983 }
984 
985 // Bugzilla 14042
986 @system unittest
987 {
988     immutable(char)* ptr = "hello".ptr;
989     auto result = ptr.to!(char[]);
990 }
991 // Bugzilla 8384
992 @system unittest
993 {
test1(T)994     void test1(T)(T lp, string cmp)
995     {
996         foreach (e; AliasSeq!(char, wchar, dchar))
997         {
998             test2!(e[])(lp, cmp);
999             test2!(const(e)[])(lp, cmp);
1000             test2!(immutable(e)[])(lp, cmp);
1001         }
1002     }
1003 
test2(D,S)1004     void test2(D, S)(S lp, string cmp)
1005     {
1006         assert(to!string(to!D(lp)) == cmp);
1007     }
1008 
1009     foreach (e; AliasSeq!("Hello, world!", "Hello, world!"w, "Hello, world!"d))
1010     {
1011         test1(e, "Hello, world!");
1012         test1(e.ptr, "Hello, world!");
1013     }
1014     foreach (e; AliasSeq!("", ""w, ""d))
1015     {
1016         test1(e, "");
1017         test1(e.ptr, "");
1018     }
1019 }
1020 
1021 /*
1022     To string conversion for non copy-able structs
1023  */
1024 private T toImpl(T, S)(ref S value)
1025 if (!(isImplicitlyConvertible!(S, T) &&
1026     !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
1027     !isInfinite!S && isExactSomeString!T && !isCopyable!S)
1028 {
1029     import std.array : appender;
1030     import std.format : FormatSpec, formatValue;
1031 
1032     auto w = appender!T();
1033     FormatSpec!(ElementEncodingType!T) f;
1034     formatValue(w, value, f);
1035     return w.data;
1036 }
1037 
1038 // Bugzilla 16108
1039 @system unittest
1040 {
1041     static struct A
1042     {
1043         int val;
1044         bool flag;
1045 
toStringA1046         string toString() { return text(val, ":", flag); }
1047 
1048         @disable this(this);
1049     }
1050 
1051     auto a = A();
1052     assert(to!string(a) == "0:false");
1053 
1054     static struct B
1055     {
1056         int val;
1057         bool flag;
1058 
1059         @disable this(this);
1060     }
1061 
1062     auto b = B();
1063     assert(to!string(b) == "B(0, false)");
1064 }
1065 
1066 /*
1067     Check whether type $(D T) can be used in a switch statement.
1068     This is useful for compile-time generation of switch case statements.
1069 */
isSwitchable(E)1070 private template isSwitchable(E)
1071 {
1072     enum bool isSwitchable = is(typeof({
1073         switch (E.init) { default: }
1074     }));
1075 }
1076 
1077 //
1078 @safe unittest
1079 {
1080     static assert(isSwitchable!int);
1081     static assert(!isSwitchable!double);
1082     static assert(!isSwitchable!real);
1083 }
1084 
1085 //Static representation of the index I of the enum S,
1086 //In representation T.
1087 //T must be an immutable string (avoids un-necessary initializations).
1088 private template enumRep(T, S, S value)
1089 if (is (T == immutable) && isExactSomeString!T && is(S == enum))
1090 {
1091     static T enumRep = toStr!T(value);
1092 }
1093 
1094 @safe pure unittest
1095 {
1096     import std.exception;
dg()1097     void dg()
1098     {
1099         // string to string conversion
1100         alias Chars = AliasSeq!(char, wchar, dchar);
1101         foreach (LhsC; Chars)
1102         {
1103             alias LhStrings = AliasSeq!(LhsC[], const(LhsC)[], immutable(LhsC)[]);
1104             foreach (Lhs; LhStrings)
1105             {
1106                 foreach (RhsC; Chars)
1107                 {
1108                     alias RhStrings = AliasSeq!(RhsC[], const(RhsC)[], immutable(RhsC)[]);
1109                     foreach (Rhs; RhStrings)
1110                     {
1111                         Lhs s1 = to!Lhs("wyda");
1112                         Rhs s2 = to!Rhs(s1);
1113                         //writeln(Lhs.stringof, " -> ", Rhs.stringof);
1114                         assert(s1 == to!Lhs(s2));
1115                     }
1116                 }
1117             }
1118         }
1119 
1120         foreach (T; Chars)
1121         {
1122             foreach (U; Chars)
1123             {
1124                 T[] s1 = to!(T[])("Hello, world!");
1125                 auto s2 = to!(U[])(s1);
1126                 assert(s1 == to!(T[])(s2));
1127                 auto s3 = to!(const(U)[])(s1);
1128                 assert(s1 == to!(T[])(s3));
1129                 auto s4 = to!(immutable(U)[])(s1);
1130                 assert(s1 == to!(T[])(s4));
1131             }
1132         }
1133     }
1134     dg();
1135     assertCTFEable!dg;
1136 }
1137 
1138 @safe pure unittest
1139 {
1140     // Conversion representing bool value with string
1141     bool b;
1142     assert(to!string(b) == "false");
1143     b = true;
1144     assert(to!string(b) == "true");
1145 }
1146 
1147 @safe pure unittest
1148 {
1149     // Conversion representing character value with string
1150     alias AllChars =
1151         AliasSeq!( char, const( char), immutable( char),
1152                   wchar, const(wchar), immutable(wchar),
1153                   dchar, const(dchar), immutable(dchar));
foreach(Char1;AllChars)1154     foreach (Char1; AllChars)
1155     {
1156         foreach (Char2; AllChars)
1157         {
1158             Char1 c = 'a';
1159             assert(to!(Char2[])(c)[0] == c);
1160         }
1161         uint x = 4;
1162         assert(to!(Char1[])(x) == "4");
1163     }
1164 
1165     string s = "foo";
1166     string s2;
foreach(char c;s)1167     foreach (char c; s)
1168     {
1169         s2 ~= to!string(c);
1170     }
1171     assert(s2 == "foo");
1172 }
1173 
1174 @safe pure nothrow unittest
1175 {
1176     import std.exception;
1177     // Conversion representing integer values with string
1178 
1179     foreach (Int; AliasSeq!(ubyte, ushort, uint, ulong))
1180     {
1181         assert(to!string(Int(0)) == "0");
1182         assert(to!string(Int(9)) == "9");
1183         assert(to!string(Int(123)) == "123");
1184     }
1185 
1186     foreach (Int; AliasSeq!(byte, short, int, long))
1187     {
1188         assert(to!string(Int(0)) == "0");
1189         assert(to!string(Int(9)) == "9");
1190         assert(to!string(Int(123)) == "123");
1191         assert(to!string(Int(-0)) == "0");
1192         assert(to!string(Int(-9)) == "-9");
1193         assert(to!string(Int(-123)) == "-123");
1194         assert(to!string(const(Int)(6)) == "6");
1195     }
1196 
1197     assert(wtext(int.max) == "2147483647"w);
1198     assert(wtext(int.min) == "-2147483648"w);
1199     assert(to!string(0L) == "0");
1200 
1201     assertCTFEable!(
1202     {
1203         assert(to!string(1uL << 62) == "4611686018427387904");
1204         assert(to!string(0x100000000) == "4294967296");
1205         assert(to!string(-138L) == "-138");
1206     });
1207 }
1208 
1209 @safe unittest // sprintf issue
1210 {
1211     double[2] a = [ 1.5, 2.5 ];
1212     assert(to!string(a) == "[1.5, 2.5]");
1213 }
1214 
1215 @system unittest
1216 {
1217     // Conversion representing class object with string
1218     class A
1219     {
toString()1220         override string toString() const { return "an A"; }
1221     }
1222     A a;
1223     assert(to!string(a) == "null");
1224     a = new A;
1225     assert(to!string(a) == "an A");
1226 
1227     // Bug 7660
toString()1228     class C { override string toString() const { return "C"; } }
1229     struct S { C c; alias c this; }
1230     S s; s.c = new C();
1231     assert(to!string(s) == "C");
1232 }
1233 
1234 @safe unittest
1235 {
1236     // Conversion representing struct object with string
1237     struct S1
1238     {
toStringS11239         string toString() { return "wyda"; }
1240     }
1241     assert(to!string(S1()) == "wyda");
1242 
1243     struct S2
1244     {
1245         int a = 42;
1246         float b = 43.5;
1247     }
1248     S2 s2;
1249     assert(to!string(s2) == "S2(42, 43.5)");
1250 
1251     // Test for issue 8080
1252     struct S8080
1253     {
1254         short[4] data;
1255         alias data this;
toStringS80801256         string toString() { return "<S>"; }
1257     }
1258     S8080 s8080;
1259     assert(to!string(s8080) == "<S>");
1260 }
1261 
1262 @safe unittest
1263 {
1264     // Conversion representing enum value with string
1265     enum EB : bool { a = true }
1266     enum EU : uint { a = 0, b = 1, c = 2 }  // base type is unsigned
1267     enum EI : int { a = -1, b = 0, c = 1 }  // base type is signed (bug 7909)
1268     enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
1269     enum EC : char { a = 'x', b = 'y' }
1270     enum ES : string { a = "aaa", b = "bbb" }
1271 
1272     foreach (E; AliasSeq!(EB, EU, EI, EF, EC, ES))
1273     {
1274         assert(to! string(E.a) == "a"c);
1275         assert(to!wstring(E.a) == "a"w);
1276         assert(to!dstring(E.a) == "a"d);
1277     }
1278 
1279     // Test an value not corresponding to an enum member.
1280     auto o = cast(EU) 5;
1281     assert(to! string(o) == "cast(EU)5"c);
1282     assert(to!wstring(o) == "cast(EU)5"w);
1283     assert(to!dstring(o) == "cast(EU)5"d);
1284 }
1285 
1286 @safe unittest
1287 {
1288     enum E
1289     {
1290         foo,
1291         doo = foo, // check duplicate switch statements
1292         bar,
1293     }
1294 
1295     //Test regression 12494
1296     assert(to!string(E.foo) == "foo");
1297     assert(to!string(E.doo) == "foo");
1298     assert(to!string(E.bar) == "bar");
1299 
1300     foreach (S; AliasSeq!(string, wstring, dstring, const(char[]), const(wchar[]), const(dchar[])))
1301     {
1302         auto s1 = to!S(E.foo);
1303         auto s2 = to!S(E.foo);
1304         assert(s1 == s2);
1305         // ensure we don't allocate when it's unnecessary
1306         assert(s1 is s2);
1307     }
1308 
1309     foreach (S; AliasSeq!(char[], wchar[], dchar[]))
1310     {
1311         auto s1 = to!S(E.foo);
1312         auto s2 = to!S(E.foo);
1313         assert(s1 == s2);
1314         // ensure each mutable array is unique
1315         assert(s1 !is s2);
1316     }
1317 }
1318 
1319 // ditto
1320 @trusted pure private T toImpl(T, S)(S value, uint radix, LetterCase letterCase = LetterCase.upper)
1321 if (isIntegral!S &&
1322     isExactSomeString!T)
1323 in
1324 {
1325     assert(radix >= 2 && radix <= 36);
1326 }
1327 body
1328 {
1329     alias EEType = Unqual!(ElementEncodingType!T);
1330 
toStringRadixConvert(size_t bufLen)1331     T toStringRadixConvert(size_t bufLen)(uint runtimeRadix = 0)
1332     {
1333         Unsigned!(Unqual!S) div = void, mValue = unsigned(value);
1334 
1335         size_t index = bufLen;
1336         EEType[bufLen] buffer = void;
1337         char baseChar = letterCase == LetterCase.lower ? 'a' : 'A';
1338         char mod = void;
1339 
1340         do
1341         {
1342             div = cast(S)(mValue / runtimeRadix );
1343             mod = cast(ubyte)(mValue % runtimeRadix);
1344             mod += mod < 10 ? '0' : baseChar - 10;
1345             buffer[--index] = cast(char) mod;
1346             mValue = div;
1347         } while (mValue);
1348 
1349         return cast(T) buffer[index .. $].dup;
1350     }
1351 
1352     import std.array : array;
1353     switch (radix)
1354     {
1355         case 10:
1356             // The (value+0) is so integral promotions happen to the type
1357             return toChars!(10, EEType)(value + 0).array;
1358         case 16:
1359             // The unsigned(unsigned(value)+0) is so unsigned integral promotions happen to the type
1360             if (letterCase == letterCase.upper)
1361                 return toChars!(16, EEType, LetterCase.upper)(unsigned(unsigned(value) + 0)).array;
1362             else
1363                 return toChars!(16, EEType, LetterCase.lower)(unsigned(unsigned(value) + 0)).array;
1364         case 2:
1365             return toChars!(2, EEType)(unsigned(unsigned(value) + 0)).array;
1366         case 8:
1367             return toChars!(8, EEType)(unsigned(unsigned(value) + 0)).array;
1368 
1369         default:
1370             return toStringRadixConvert!(S.sizeof * 6)(radix);
1371     }
1372 }
1373 
1374 @safe pure nothrow unittest
1375 {
1376     foreach (Int; AliasSeq!(uint, ulong))
1377     {
1378         assert(to!string(Int(16), 16) == "10");
1379         assert(to!string(Int(15), 2u) == "1111");
1380         assert(to!string(Int(1), 2u) == "1");
1381         assert(to!string(Int(0x1234AF), 16u) == "1234AF");
1382         assert(to!string(Int(0x1234BCD), 16u, LetterCase.upper) == "1234BCD");
1383         assert(to!string(Int(0x1234AF), 16u, LetterCase.lower) == "1234af");
1384     }
1385 
1386     foreach (Int; AliasSeq!(int, long))
1387     {
1388         assert(to!string(Int(-10), 10u) == "-10");
1389     }
1390 
1391     assert(to!string(byte(-10), 16) == "F6");
1392     assert(to!string(long.min) == "-9223372036854775808");
1393     assert(to!string(long.max) == "9223372036854775807");
1394 }
1395 
1396 /**
1397 Narrowing numeric-numeric conversions throw when the value does not
1398 fit in the narrower type.
1399  */
1400 private T toImpl(T, S)(S value)
1401 if (!isImplicitlyConvertible!(S, T) &&
1402     (isNumeric!S || isSomeChar!S || isBoolean!S) &&
1403     (isNumeric!T || isSomeChar!T || isBoolean!T) && !is(T == enum))
1404 {
1405     enum sSmallest = mostNegative!S;
1406     enum tSmallest = mostNegative!T;
1407     static if (sSmallest < 0)
1408     {
1409         // possible underflow converting from a signed
1410         static if (tSmallest == 0)
1411         {
1412             immutable good = value >= 0;
1413         }
1414         else
1415         {
1416             static assert(tSmallest < 0);
1417             immutable good = value >= tSmallest;
1418         }
1419         if (!good)
1420             throw new ConvOverflowException("Conversion negative overflow");
1421     }
1422     static if (S.max > T.max)
1423     {
1424         // possible overflow
1425         if (value > T.max)
1426             throw new ConvOverflowException("Conversion positive overflow");
1427     }
1428     return (ref value)@trusted{ return cast(T) value; }(value);
1429 }
1430 
1431 @safe pure unittest
1432 {
1433     import std.exception;
1434 
1435     dchar a = ' ';
1436     assert(to!char(a) == ' ');
1437     a = 300;
1438     assert(collectException(to!char(a)));
1439 
1440     dchar from0 = 'A';
1441     char to0 = to!char(from0);
1442 
1443     wchar from1 = 'A';
1444     char to1 = to!char(from1);
1445 
1446     char from2 = 'A';
1447     char to2 = to!char(from2);
1448 
1449     char from3 = 'A';
1450     wchar to3 = to!wchar(from3);
1451 
1452     char from4 = 'A';
1453     dchar to4 = to!dchar(from4);
1454 }
1455 
1456 @safe unittest
1457 {
1458     import std.exception;
1459 
1460     // Narrowing conversions from enum -> integral should be allowed, but they
1461     // should throw at runtime if the enum value doesn't fit in the target
1462     // type.
1463     enum E1 : ulong { A = 1, B = 1UL << 48, C = 0 }
1464     assert(to!int(E1.A) == 1);
1465     assert(to!bool(E1.A) == true);
1466     assertThrown!ConvOverflowException(to!int(E1.B)); // E1.B overflows int
1467     assertThrown!ConvOverflowException(to!bool(E1.B)); // E1.B overflows bool
1468     assert(to!bool(E1.C) == false);
1469 
1470     enum E2 : long { A = -1L << 48, B = -1 << 31, C = 1 << 31 }
1471     assertThrown!ConvOverflowException(to!int(E2.A)); // E2.A overflows int
1472     assertThrown!ConvOverflowException(to!uint(E2.B)); // E2.B overflows uint
1473     assert(to!int(E2.B) == -1 << 31); // but does not overflow int
1474     assert(to!int(E2.C) == 1 << 31);  // E2.C does not overflow int
1475 
1476     enum E3 : int { A = -1, B = 1, C = 255, D = 0 }
1477     assertThrown!ConvOverflowException(to!ubyte(E3.A));
1478     assertThrown!ConvOverflowException(to!bool(E3.A));
1479     assert(to!byte(E3.A) == -1);
1480     assert(to!byte(E3.B) == 1);
1481     assert(to!ubyte(E3.C) == 255);
1482     assert(to!bool(E3.B) == true);
1483     assertThrown!ConvOverflowException(to!byte(E3.C));
1484     assertThrown!ConvOverflowException(to!bool(E3.C));
1485     assert(to!bool(E3.D) == false);
1486 
1487 }
1488 
1489 /**
1490 Array-to-array conversion (except when target is a string type)
1491 converts each element in turn by using $(D to).
1492  */
1493 private T toImpl(T, S)(S value)
1494 if (!isImplicitlyConvertible!(S, T) &&
1495     !isSomeString!S && isDynamicArray!S &&
1496     !isExactSomeString!T && isArray!T)
1497 {
1498     alias E = typeof(T.init[0]);
1499 
1500     static if (isStaticArray!T)
1501     {
1502         import std.exception : enforce;
1503         auto res = to!(E[])(value);
1504         enforce!ConvException(T.length == res.length,
1505             convFormat("Length mismatch when converting to static array: %s vs %s", T.length, res.length));
1506         return res[0 .. T.length];
1507     }
1508     else
1509     {
1510         import std.array : appender;
1511         auto w = appender!(E[])();
1512         w.reserve(value.length);
foreach(i,ref e;value)1513         foreach (i, ref e; value)
1514         {
1515             w.put(to!E(e));
1516         }
1517         return w.data;
1518     }
1519 }
1520 
1521 @safe pure unittest
1522 {
1523     import std.exception;
1524 
1525     // array to array conversions
1526     uint[] a = [ 1u, 2, 3 ];
1527     auto b = to!(float[])(a);
1528     assert(b == [ 1.0f, 2, 3 ]);
1529 
1530     immutable(int)[3] d = [ 1, 2, 3 ];
1531     b = to!(float[])(d);
1532     assert(b == [ 1.0f, 2, 3 ]);
1533 
1534     uint[][] e = [ a, a ];
1535     auto f = to!(float[][])(e);
1536     assert(f[0] == b && f[1] == b);
1537 
1538     // Test for bug 8264
1539     struct Wrap
1540     {
1541         string wrap;
1542         alias wrap this;
1543     }
1544     Wrap[] warr = to!(Wrap[])(["foo", "bar"]);  // should work
1545 
1546     // Issue 12633
1547     import std.conv : to;
1548     const s2 = ["10", "20"];
1549 
1550     immutable int[2] a3 = s2.to!(int[2]);
1551     assert(a3 == [10, 20]);
1552 
1553     // verify length mismatches are caught
1554     immutable s4 = [1, 2, 3, 4];
foreach(i;[1,4])1555     foreach (i; [1, 4])
1556     {
1557         auto ex = collectException(s4[0 .. i].to!(int[2]));
1558             assert(ex && ex.msg == "Length mismatch when converting to static array: 2 vs " ~ [cast(char)(i + '0')],
1559                 ex ? ex.msg : "Exception was not thrown!");
1560     }
1561 }
1562 
1563 @safe unittest
1564 {
1565     auto b = [ 1.0f, 2, 3 ];
1566 
1567     auto c = to!(string[])(b);
1568     assert(c[0] == "1" && c[1] == "2" && c[2] == "3");
1569 }
1570 
1571 /**
1572 Associative array to associative array conversion converts each key
1573 and each value in turn.
1574  */
1575 private T toImpl(T, S)(S value)
1576 if (isAssociativeArray!S &&
1577     isAssociativeArray!T && !is(T == enum))
1578 {
1579     /* This code is potentially unsafe.
1580      */
1581     alias K2 = KeyType!T;
1582     alias V2 = ValueType!T;
1583 
1584     // While we are "building" the AA, we need to unqualify its values, and only re-qualify at the end
1585     Unqual!V2[K2] result;
1586 
foreach(k1,v1;value)1587     foreach (k1, v1; value)
1588     {
1589         // Cast values temporarily to Unqual!V2 to store them to result variable
1590         result[to!K2(k1)] = cast(Unqual!V2) to!V2(v1);
1591     }
1592     // Cast back to original type
1593     return cast(T) result;
1594 }
1595 
1596 @safe unittest
1597 {
1598     // hash to hash conversions
1599     int[string] a;
1600     a["0"] = 1;
1601     a["1"] = 2;
1602     auto b = to!(double[dstring])(a);
1603     assert(b["0"d] == 1 && b["1"d] == 2);
1604 }
1605 @safe unittest // Bugzilla 8705, from doc
1606 {
1607     import std.exception;
1608     int[string][double[int[]]] a;
1609     auto b = to!(short[wstring][string[double[]]])(a);
1610     a = [null:["hello":int.max]];
1611     assertThrown!ConvOverflowException(to!(short[wstring][string[double[]]])(a));
1612 }
1613 @system unittest // Extra cases for AA with qualifiers conversion
1614 {
1615     int[][int[]] a;// = [[], []];
1616     auto b = to!(immutable(short[])[immutable short[]])(a);
1617 
1618     double[dstring][int[long[]]] c;
1619     auto d = to!(immutable(short[immutable wstring])[immutable string[double[]]])(c);
1620 }
1621 
testIntegralToFloating(Integral,Floating)1622 private void testIntegralToFloating(Integral, Floating)()
1623 {
1624     Integral a = 42;
1625     auto b = to!Floating(a);
1626     assert(a == b);
1627     assert(a == to!Integral(b));
1628 }
1629 
testFloatingToIntegral(Floating,Integral)1630 private void testFloatingToIntegral(Floating, Integral)()
1631 {
1632     bool convFails(Source, Target, E)(Source src)
1633     {
1634         try
1635             auto t = to!Target(src);
1636         catch (E)
1637             return true;
1638         return false;
1639     }
1640 
1641     // convert some value
1642     Floating a = 4.2e1;
1643     auto b = to!Integral(a);
1644     assert(is(typeof(b) == Integral) && b == 42);
1645     // convert some negative value (if applicable)
1646     a = -4.2e1;
1647     static if (Integral.min < 0)
1648     {
1649         b = to!Integral(a);
1650         assert(is(typeof(b) == Integral) && b == -42);
1651     }
1652     else
1653     {
1654         // no go for unsigned types
1655         assert(convFails!(Floating, Integral, ConvOverflowException)(a));
1656     }
1657     // convert to the smallest integral value
1658     a = 0.0 + Integral.min;
1659     static if (Integral.min < 0)
1660     {
1661         a = -a; // -Integral.min not representable as an Integral
1662         assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1663                 || Floating.sizeof <= Integral.sizeof);
1664     }
1665     a = 0.0 + Integral.min;
1666     assert(to!Integral(a) == Integral.min);
1667     --a; // no more representable as an Integral
1668     assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1669             || Floating.sizeof <= Integral.sizeof);
1670     a = 0.0 + Integral.max;
1671     assert(to!Integral(a) == Integral.max || Floating.sizeof <= Integral.sizeof);
1672     ++a; // no more representable as an Integral
1673     assert(convFails!(Floating, Integral, ConvOverflowException)(a)
1674             || Floating.sizeof <= Integral.sizeof);
1675     // convert a value with a fractional part
1676     a = 3.14;
1677     assert(to!Integral(a) == 3);
1678     a = 3.99;
1679     assert(to!Integral(a) == 3);
1680     static if (Integral.min < 0)
1681     {
1682         a = -3.14;
1683         assert(to!Integral(a) == -3);
1684         a = -3.99;
1685         assert(to!Integral(a) == -3);
1686     }
1687 }
1688 
1689 @safe pure unittest
1690 {
1691     alias AllInts = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong);
1692     alias AllFloats = AliasSeq!(float, double, real);
1693     alias AllNumerics = AliasSeq!(AllInts, AllFloats);
1694     // test with same type
1695     {
foreach(T;AllNumerics)1696         foreach (T; AllNumerics)
1697         {
1698             T a = 42;
1699             auto b = to!T(a);
1700             assert(is(typeof(a) == typeof(b)) && a == b);
1701         }
1702     }
1703     // test that floating-point numbers convert properly to largest ints
1704     // see http://oregonstate.edu/~peterseb/mth351/docs/351s2001_fp80x87.html
1705     // look for "largest fp integer with a predecessor"
1706     {
1707         // float
1708         int a = 16_777_215; // 2^24 - 1
1709         assert(to!int(to!float(a)) == a);
1710         assert(to!int(to!float(-a)) == -a);
1711         // double
1712         long b = 9_007_199_254_740_991; // 2^53 - 1
1713         assert(to!long(to!double(b)) == b);
1714         assert(to!long(to!double(-b)) == -b);
1715         // real
1716         static if (real.mant_dig >= 64)
1717         {
1718             ulong c = 18_446_744_073_709_551_615UL; // 2^64 - 1
1719             assert(to!ulong(to!real(c)) == c);
1720         }
1721     }
1722     // test conversions floating => integral
1723     {
1724         // AllInts[0 .. $ - 1] should be AllInts
1725         // @@@ BUG IN COMPILER @@@
foreach(Integral;AllInts[0..$-1])1726         foreach (Integral; AllInts[0 .. $ - 1])
1727         {
1728             foreach (Floating; AllFloats)
1729             {
1730                 testFloatingToIntegral!(Floating, Integral)();
1731             }
1732         }
1733     }
1734     // test conversion integral => floating
1735     {
foreach(Integral;AllInts[0..$-1])1736         foreach (Integral; AllInts[0 .. $ - 1])
1737         {
1738             foreach (Floating; AllFloats)
1739             {
1740                 testIntegralToFloating!(Integral, Floating)();
1741             }
1742         }
1743     }
1744     // test parsing
1745     {
foreach(T;AllNumerics)1746         foreach (T; AllNumerics)
1747         {
1748             // from type immutable(char)[2]
1749             auto a = to!T("42");
1750             assert(a == 42);
1751             // from type char[]
1752             char[] s1 = "42".dup;
1753             a = to!T(s1);
1754             assert(a == 42);
1755             // from type char[2]
1756             char[2] s2;
1757             s2[] = "42";
1758             a = to!T(s2);
1759             assert(a == 42);
1760             // from type immutable(wchar)[2]
1761             a = to!T("42"w);
1762             assert(a == 42);
1763         }
1764     }
1765 }
1766 
1767 @safe unittest
1768 {
1769     alias AllInts = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong);
1770     alias AllFloats = AliasSeq!(float, double, real);
1771     alias AllNumerics = AliasSeq!(AllInts, AllFloats);
1772     // test conversions to string
1773     {
foreach(T;AllNumerics)1774         foreach (T; AllNumerics)
1775         {
1776             T a = 42;
1777             assert(to!string(a) == "42");
1778             assert(to!wstring(a) == "42"w);
1779             assert(to!dstring(a) == "42"d);
1780             // array test
1781             T[] b = new T[2];
1782             b[0] = 42;
1783             b[1] = 33;
1784             assert(to!string(b) == "[42, 33]");
1785         }
1786     }
1787     // test array to string conversion
foreach(T;AllNumerics)1788     foreach (T ; AllNumerics)
1789     {
1790         auto a = [to!T(1), 2, 3];
1791         assert(to!string(a) == "[1, 2, 3]");
1792     }
1793     // test enum to int conversion
1794     enum Testing { Test1, Test2 }
1795     Testing t;
1796     auto a = to!string(t);
1797     assert(a == "Test1");
1798 }
1799 
1800 
1801 /**
1802 String, or string-like input range, to non-string conversion runs parsing.
1803 $(UL
1804   $(LI When the source is a wide string, it is first converted to a narrow
1805        string and then parsed.)
1806   $(LI When the source is a narrow string, normal text parsing occurs.))
1807 */
1808 private T toImpl(T, S)(S value)
1809 if (isInputRange!S && isSomeChar!(ElementEncodingType!S) &&
1810     !isExactSomeString!T && is(typeof(parse!T(value))))
1811 {
scope(success)1812     scope(success)
1813     {
1814         if (!value.empty)
1815         {
1816             throw convError!(S, T)(value);
1817         }
1818     }
1819     return parse!T(value);
1820 }
1821 
1822 /// ditto
1823 private T toImpl(T, S)(S value, uint radix)
1824 if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S) &&
1825     isIntegral!T && is(typeof(parse!T(value, radix))))
1826 {
scope(success)1827     scope(success)
1828     {
1829         if (!value.empty)
1830         {
1831             throw convError!(S, T)(value);
1832         }
1833     }
1834     return parse!T(value, radix);
1835 }
1836 
1837 @safe pure unittest
1838 {
1839     // Issue 6668 - ensure no collaterals thrown
1840     try { to!uint("-1"); }
catch(ConvException e)1841     catch (ConvException e) { assert(e.next is null); }
1842 }
1843 
1844 @safe pure unittest
1845 {
1846     foreach (Str; AliasSeq!(string, wstring, dstring))
1847     {
1848         Str a = "123";
1849         assert(to!int(a) == 123);
1850         assert(to!double(a) == 123);
1851     }
1852 
1853     // 6255
1854     auto n = to!int("FF", 16);
1855     assert(n == 255);
1856 }
1857 
1858 // bugzilla 15800
1859 @safe unittest
1860 {
1861     import std.utf : byCodeUnit, byChar, byWchar, byDchar;
1862 
1863     assert(to!int(byCodeUnit("10")) == 10);
1864     assert(to!int(byCodeUnit("10"), 10) == 10);
1865     assert(to!int(byCodeUnit("10"w)) == 10);
1866     assert(to!int(byCodeUnit("10"w), 10) == 10);
1867 
1868     assert(to!int(byChar("10")) == 10);
1869     assert(to!int(byChar("10"), 10) == 10);
1870     assert(to!int(byWchar("10")) == 10);
1871     assert(to!int(byWchar("10"), 10) == 10);
1872     assert(to!int(byDchar("10")) == 10);
1873     assert(to!int(byDchar("10"), 10) == 10);
1874 }
1875 
1876 /**
1877 Convert a value that is implicitly convertible to the enum base type
1878 into an Enum value. If the value does not match any enum member values
1879 a ConvException is thrown.
1880 Enums with floating-point or string base types are not supported.
1881 */
1882 private T toImpl(T, S)(S value)
1883 if (is(T == enum) && !is(S == enum)
1884     && is(typeof(value == OriginalType!T.init))
1885     && !isFloatingPoint!(OriginalType!T) && !isSomeString!(OriginalType!T))
1886 {
1887     foreach (Member; EnumMembers!T)
1888     {
1889         if (Member == value)
1890             return Member;
1891     }
1892     throw new ConvException(convFormat("Value (%s) does not match any member value of enum '%s'", value, T.stringof));
1893 }
1894 
1895 @safe pure unittest
1896 {
1897     import std.exception;
1898     enum En8143 : int { A = 10, B = 20, C = 30, D = 20 }
1899     enum En8143[][] m3 = to!(En8143[][])([[10, 30], [30, 10]]);
1900     static assert(m3 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
1901 
1902     En8143 en1 = to!En8143(10);
1903     assert(en1 == En8143.A);
1904     assertThrown!ConvException(to!En8143(5));   // matches none
1905     En8143[][] m1 = to!(En8143[][])([[10, 30], [30, 10]]);
1906     assert(m1 == [[En8143.A, En8143.C], [En8143.C, En8143.A]]);
1907 }
1908 
1909 /***************************************************************
1910  Rounded conversion from floating point to integral.
1911 
1912 Rounded conversions do not work with non-integral target types.
1913  */
1914 
roundTo(Target)1915 template roundTo(Target)
1916 {
1917     Target roundTo(Source)(Source value)
1918     {
1919         import std.math : trunc;
1920 
1921         static assert(isFloatingPoint!Source);
1922         static assert(isIntegral!Target);
1923         return to!Target(trunc(value + (value < 0 ? -0.5L : 0.5L)));
1924     }
1925 }
1926 
1927 ///
1928 @safe unittest
1929 {
1930     assert(roundTo!int(3.14) == 3);
1931     assert(roundTo!int(3.49) == 3);
1932     assert(roundTo!int(3.5) == 4);
1933     assert(roundTo!int(3.999) == 4);
1934     assert(roundTo!int(-3.14) == -3);
1935     assert(roundTo!int(-3.49) == -3);
1936     assert(roundTo!int(-3.5) == -4);
1937     assert(roundTo!int(-3.999) == -4);
1938     assert(roundTo!(const int)(to!(const double)(-3.999)) == -4);
1939 }
1940 
1941 @safe unittest
1942 {
1943     import std.exception;
1944     // boundary values
1945     foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint))
1946     {
1947         assert(roundTo!Int(Int.min - 0.4L) == Int.min);
1948         assert(roundTo!Int(Int.max + 0.4L) == Int.max);
1949         assertThrown!ConvOverflowException(roundTo!Int(Int.min - 0.5L));
1950         assertThrown!ConvOverflowException(roundTo!Int(Int.max + 0.5L));
1951     }
1952 }
1953 
1954 /**
1955 The $(D parse) family of functions works quite like the $(D to)
1956 family, except that:
1957 $(OL
1958     $(LI It only works with character ranges as input.)
1959     $(LI It takes the input by reference. (This means that rvalues - such
1960     as string literals - are not accepted: use $(D to) instead.))
1961     $(LI It advances the input to the position following the conversion.)
1962     $(LI It does not throw if it could not convert the entire input.))
1963 
1964 This overload converts an character input range to a `bool`.
1965 
1966 Params:
1967     Target = the type to convert to
1968     source = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
1969 
1970 Returns:
1971     A `bool`
1972 
1973 Throws:
1974     A $(LREF ConvException) if the range does not represent a `bool`.
1975 
1976 Note:
1977     All character input range conversions using $(LREF to) are forwarded
1978     to `parse` and do not require lvalues.
1979 */
1980 Target parse(Target, Source)(ref Source source)
1981 if (isInputRange!Source &&
1982     isSomeChar!(ElementType!Source) &&
1983     is(Unqual!Target == bool))
1984 {
1985     import std.ascii : toLower;
1986 
1987     static if (isNarrowString!Source)
1988     {
1989         import std.string : representation;
1990         auto s = source.representation;
1991     }
1992     else
1993     {
1994         alias s = source;
1995     }
1996 
1997     if (!s.empty)
1998     {
1999         auto c1 = toLower(s.front);
2000         bool result = c1 == 't';
2001         if (result || c1 == 'f')
2002         {
2003             s.popFront();
2004             foreach (c; result ? "rue" : "alse")
2005             {
2006                 if (s.empty || toLower(s.front) != c)
2007                     goto Lerr;
2008                 s.popFront();
2009             }
2010 
2011             static if (isNarrowString!Source)
2012                 source = cast(Source) s;
2013 
2014             return result;
2015         }
2016     }
2017 Lerr:
2018     throw parseError("bool should be case-insensitive 'true' or 'false'");
2019 }
2020 
2021 ///
2022 @safe unittest
2023 {
2024     auto s = "true";
2025     bool b = parse!bool(s);
2026     assert(b);
2027 }
2028 
2029 @safe unittest
2030 {
2031     import std.algorithm.comparison : equal;
2032     import std.exception;
2033     struct InputString
2034     {
2035         string _s;
frontInputString2036         @property auto front() { return _s.front; }
emptyInputString2037         @property bool empty() { return _s.empty; }
popFrontInputString2038         void popFront() { _s.popFront(); }
2039     }
2040 
2041     auto s = InputString("trueFALSETrueFalsetRUEfALSE");
2042     assert(parse!bool(s) == true);
2043     assert(s.equal("FALSETrueFalsetRUEfALSE"));
2044     assert(parse!bool(s) == false);
2045     assert(s.equal("TrueFalsetRUEfALSE"));
2046     assert(parse!bool(s) == true);
2047     assert(s.equal("FalsetRUEfALSE"));
2048     assert(parse!bool(s) == false);
2049     assert(s.equal("tRUEfALSE"));
2050     assert(parse!bool(s) == true);
2051     assert(s.equal("fALSE"));
2052     assert(parse!bool(s) == false);
2053     assert(s.empty);
2054 
foreach(ss;["tfalse","ftrue","t","f","tru","fals",""])2055     foreach (ss; ["tfalse", "ftrue", "t", "f", "tru", "fals", ""])
2056     {
2057         s = InputString(ss);
2058         assertThrown!ConvException(parse!bool(s));
2059     }
2060 }
2061 
2062 /**
2063 Parses a character $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
2064 to an integral value.
2065 
2066 Params:
2067     Target = the integral type to convert to
2068     s = the lvalue of an input range
2069 
2070 Returns:
2071     A number of type `Target`
2072 
2073 Throws:
2074     A $(LREF ConvException) If an overflow occurred during conversion or
2075     if no character of the input was meaningfully converted.
2076 */
2077 Target parse(Target, Source)(ref Source s)
2078 if (isSomeChar!(ElementType!Source) &&
2079     isIntegral!Target && !is(Target == enum))
2080 {
2081     static if (Target.sizeof < int.sizeof)
2082     {
2083         // smaller types are handled like integers
2084         auto v = .parse!(Select!(Target.min < 0, int, uint))(s);
2085         auto result = ()@trusted{ return cast(Target) v; }();
2086         if (result == v)
2087             return result;
2088         throw new ConvOverflowException("Overflow in integral conversion");
2089     }
2090     else
2091     {
2092         // int or larger types
2093 
2094         static if (Target.min < 0)
2095             bool sign = false;
2096         else
2097             enum bool sign = false;
2098 
2099         enum char maxLastDigit = Target.min < 0 ? 7 : 5;
2100         uint c;
2101 
2102         static if (isNarrowString!Source)
2103         {
2104             import std.string : representation;
2105             auto source = s.representation;
2106         }
2107         else
2108         {
2109             alias source = s;
2110         }
2111 
2112         if (source.empty)
2113             goto Lerr;
2114 
2115         c = source.front;
2116 
2117         static if (Target.min < 0)
2118         {
2119             switch (c)
2120             {
2121                 case '-':
2122                     sign = true;
2123                     goto case '+';
2124                 case '+':
2125                     source.popFront();
2126 
2127                     if (source.empty)
2128                         goto Lerr;
2129 
2130                     c = source.front;
2131 
2132                     break;
2133 
2134                 default:
2135                     break;
2136             }
2137         }
2138         c -= '0';
2139         if (c <= 9)
2140         {
2141             Target v = cast(Target) c;
2142 
2143             source.popFront();
2144 
2145             while (!source.empty)
2146             {
2147                 c = cast(typeof(c)) (source.front - '0');
2148 
2149                 if (c > 9)
2150                     break;
2151 
2152                 if (v >= 0 && (v < Target.max/10 ||
2153                     (v == Target.max/10 && c <= maxLastDigit + sign)))
2154                 {
2155                     // Note: `v` can become negative here in case of parsing
2156                     // the most negative value:
2157                     v = cast(Target) (v * 10 + c);
2158 
2159                     source.popFront();
2160                 }
2161                 else
2162                     throw new ConvOverflowException("Overflow in integral conversion");
2163             }
2164 
2165             if (sign)
2166                 v = -v;
2167 
2168             static if (isNarrowString!Source)
2169                 s = cast(Source) source;
2170 
2171             return v;
2172         }
2173 Lerr:
2174         static if (isNarrowString!Source)
2175             throw convError!(Source, Target)(cast(Source) source);
2176         else
2177             throw convError!(Source, Target)(source);
2178     }
2179 }
2180 
2181 ///
2182 @safe pure unittest
2183 {
2184     string s = "123";
2185     auto a = parse!int(s);
2186     assert(a == 123);
2187 
2188     // parse only accepts lvalues
2189     static assert(!__traits(compiles, parse!int("123")));
2190 }
2191 
2192 ///
2193 @safe pure unittest
2194 {
2195     import std.string : tr;
2196     string test = "123 \t  76.14";
2197     auto a = parse!uint(test);
2198     assert(a == 123);
2199     assert(test == " \t  76.14"); // parse bumps string
2200     test = tr(test, " \t\n\r", "", "d"); // skip ws
2201     assert(test == "76.14");
2202     auto b = parse!double(test);
2203     assert(b == 76.14);
2204     assert(test == "");
2205 }
2206 
2207 @safe pure unittest
2208 {
2209     foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2210     {
2211         {
2212             assert(to!Int("0") == 0);
2213 
2214             static if (isSigned!Int)
2215             {
2216                 assert(to!Int("+0") == 0);
2217                 assert(to!Int("-0") == 0);
2218             }
2219         }
2220 
2221         static if (Int.sizeof >= byte.sizeof)
2222         {
2223                 assert(to!Int("6") == 6);
2224                 assert(to!Int("23") == 23);
2225                 assert(to!Int("68") == 68);
2226                 assert(to!Int("127") == 0x7F);
2227 
2228             static if (isUnsigned!Int)
2229             {
2230                 assert(to!Int("255") == 0xFF);
2231             }
2232             static if (isSigned!Int)
2233             {
2234                 assert(to!Int("+6") == 6);
2235                 assert(to!Int("+23") == 23);
2236                 assert(to!Int("+68") == 68);
2237                 assert(to!Int("+127") == 0x7F);
2238 
2239                 assert(to!Int("-6") == -6);
2240                 assert(to!Int("-23") == -23);
2241                 assert(to!Int("-68") == -68);
2242                 assert(to!Int("-128") == -128);
2243             }
2244         }
2245 
2246         static if (Int.sizeof >= short.sizeof)
2247         {
2248                 assert(to!Int("468") == 468);
2249                 assert(to!Int("32767") == 0x7FFF);
2250 
2251             static if (isUnsigned!Int)
2252             {
2253                 assert(to!Int("65535") == 0xFFFF);
2254             }
2255             static if (isSigned!Int)
2256             {
2257                 assert(to!Int("+468") == 468);
2258                 assert(to!Int("+32767") == 0x7FFF);
2259 
2260                 assert(to!Int("-468") == -468);
2261                 assert(to!Int("-32768") == -32768);
2262             }
2263         }
2264 
2265         static if (Int.sizeof >= int.sizeof)
2266         {
2267                 assert(to!Int("2147483647") == 0x7FFFFFFF);
2268 
2269             static if (isUnsigned!Int)
2270             {
2271                 assert(to!Int("4294967295") == 0xFFFFFFFF);
2272             }
2273 
2274             static if (isSigned!Int)
2275             {
2276                 assert(to!Int("+2147483647") == 0x7FFFFFFF);
2277 
2278                 assert(to!Int("-2147483648") == -2147483648);
2279             }
2280         }
2281 
2282         static if (Int.sizeof >= long.sizeof)
2283         {
2284                 assert(to!Int("9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
2285 
2286             static if (isUnsigned!Int)
2287             {
2288                 assert(to!Int("18446744073709551615") == 0xFFFFFFFFFFFFFFFF);
2289             }
2290 
2291             static if (isSigned!Int)
2292             {
2293                 assert(to!Int("+9223372036854775807") == 0x7FFFFFFFFFFFFFFF);
2294 
2295                 assert(to!Int("-9223372036854775808") == 0x8000000000000000);
2296             }
2297         }
2298     }
2299 }
2300 
2301 @safe pure unittest
2302 {
2303     import std.exception;
2304     // parsing error check
2305     foreach (Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2306     {
2307         {
2308             immutable string[] errors1 =
2309             [
2310                 "",
2311                 "-",
2312                 "+",
2313                 "-+",
2314                 " ",
2315                 " 0",
2316                 "0 ",
2317                 "- 0",
2318                 "1-",
2319                 "xx",
2320                 "123h",
2321                 "-+1",
2322                 "--1",
2323                 "+-1",
2324                 "++1",
2325             ];
2326             foreach (j, s; errors1)
2327                 assertThrown!ConvException(to!Int(s));
2328         }
2329 
2330         // parse!SomeUnsigned cannot parse head sign.
2331         static if (isUnsigned!Int)
2332         {
2333             immutable string[] errors2 =
2334             [
2335                 "+5",
2336                 "-78",
2337             ];
2338             foreach (j, s; errors2)
2339                 assertThrown!ConvException(to!Int(s));
2340         }
2341     }
2342 
2343     // positive overflow check
2344     foreach (i, Int; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
2345     {
2346         immutable string[] errors =
2347         [
2348             "128",                  // > byte.max
2349             "256",                  // > ubyte.max
2350             "32768",                // > short.max
2351             "65536",                // > ushort.max
2352             "2147483648",           // > int.max
2353             "4294967296",           // > uint.max
2354             "9223372036854775808",  // > long.max
2355             "18446744073709551616", // > ulong.max
2356         ];
2357         foreach (j, s; errors[i..$])
2358             assertThrown!ConvOverflowException(to!Int(s));
2359     }
2360 
2361     // negative overflow check
2362     foreach (i, Int; AliasSeq!(byte, short, int, long))
2363     {
2364         immutable string[] errors =
2365         [
2366             "-129",                 // < byte.min
2367             "-32769",               // < short.min
2368             "-2147483649",          // < int.min
2369             "-9223372036854775809", // < long.min
2370         ];
2371         foreach (j, s; errors[i..$])
2372             assertThrown!ConvOverflowException(to!Int(s));
2373     }
2374 }
2375 
2376 @safe pure unittest
2377 {
checkErrMsg(string input,dchar charInMsg,dchar charNotInMsg)2378     void checkErrMsg(string input, dchar charInMsg, dchar charNotInMsg)
2379     {
2380         try
2381         {
2382             int x = input.to!int();
2383             assert(false, "Invalid conversion did not throw");
2384         }
2385         catch (ConvException e)
2386         {
2387             // Ensure error message contains failing character, not the character
2388             // beyond.
2389             import std.algorithm.searching : canFind;
2390             assert( e.msg.canFind(charInMsg) &&
2391                    !e.msg.canFind(charNotInMsg));
2392         }
2393         catch (Exception e)
2394         {
2395             assert(false, "Did not throw ConvException");
2396         }
2397     }
2398     checkErrMsg("@$", '@', '$');
2399     checkErrMsg("@$123", '@', '$');
2400     checkErrMsg("1@$23", '@', '$');
2401     checkErrMsg("1@$", '@', '$');
2402     checkErrMsg("1@$2", '@', '$');
2403     checkErrMsg("12@$", '@', '$');
2404 }
2405 
2406 @safe pure unittest
2407 {
2408     import std.exception;
2409     assertCTFEable!({ string s =  "1234abc"; assert(parse! int(s) ==  1234 && s == "abc"); });
2410     assertCTFEable!({ string s = "-1234abc"; assert(parse! int(s) == -1234 && s == "abc"); });
2411     assertCTFEable!({ string s =  "1234abc"; assert(parse!uint(s) ==  1234 && s == "abc"); });
2412 }
2413 
2414 // Issue 13931
2415 @safe pure unittest
2416 {
2417     import std.exception;
2418 
2419     assertThrown!ConvOverflowException("-21474836480".to!int());
2420     assertThrown!ConvOverflowException("-92233720368547758080".to!long());
2421 }
2422 
2423 // Issue 14396
2424 @safe pure unittest
2425 {
2426     struct StrInputRange
2427     {
thisStrInputRange2428         this (string s) { str = s; }
frontStrInputRange2429         char front() const @property { return str[front_index]; }
popFrontStrInputRange2430         char popFront() { return str[front_index++]; }
emptyStrInputRange2431         bool empty() const @property { return str.length <= front_index; }
2432         string str;
2433         size_t front_index = 0;
2434     }
2435     auto input = StrInputRange("777");
2436     assert(parse!int(input) == 777);
2437 }
2438 
2439 /// ditto
2440 Target parse(Target, Source)(ref Source source, uint radix)
2441 if (isSomeChar!(ElementType!Source) &&
2442     isIntegral!Target && !is(Target == enum))
2443 in
2444 {
2445     assert(radix >= 2 && radix <= 36);
2446 }
2447 body
2448 {
2449     import core.checkedint : mulu, addu;
2450     import std.exception : enforce;
2451 
2452     if (radix == 10)
2453         return parse!Target(source);
2454 
2455     enforce!ConvException(!source.empty, "s must not be empty in integral parse");
2456 
2457     immutable uint beyond = (radix < 10 ? '0' : 'a'-10) + radix;
2458     Target v = 0;
2459 
2460     static if (isNarrowString!Source)
2461     {
2462         import std.string : representation;
2463         auto s = source.representation;
2464     }
2465     else
2466     {
2467         alias s = source;
2468     }
2469 
2470     do
2471     {
2472         uint c = s.front;
2473         if (c < '0')
2474             break;
2475         if (radix < 10)
2476         {
2477             if (c >= beyond)
2478                 break;
2479         }
2480         else
2481         {
2482             if (c > '9')
2483             {
2484                 c |= 0x20;//poorman's tolower
2485                 if (c < 'a' || c >= beyond)
2486                     break;
2487                 c -= 'a'-10-'0';
2488             }
2489         }
2490 
2491         bool overflow = false;
2492         auto nextv = v.mulu(radix, overflow).addu(c - '0', overflow);
2493         enforce!ConvOverflowException(!overflow && nextv <= Target.max, "Overflow in integral conversion");
2494         v = cast(Target) nextv;
2495         s.popFront();
2496     } while (!s.empty);
2497 
2498     static if (isNarrowString!Source)
2499         source = cast(Source) s;
2500 
2501     return v;
2502 }
2503 
2504 @safe pure unittest
2505 {
2506     string s; // parse doesn't accept rvalues
2507     foreach (i; 2 .. 37)
2508     {
2509         assert(parse!int(s = "0", i) == 0);
2510         assert(parse!int(s = "1", i) == 1);
2511         assert(parse!byte(s = "10", i) == i);
2512     }
2513 
2514     assert(parse!int(s = "0011001101101", 2) == 0b0011001101101);
2515     assert(parse!int(s = "765", 8) == octal!765);
2516     assert(parse!int(s = "fCDe", 16) == 0xfcde);
2517 
2518     // 6609
2519     assert(parse!int(s = "-42", 10) == -42);
2520 
2521     assert(parse!ubyte(s = "ff", 16) == 0xFF);
2522 }
2523 
2524 @safe pure unittest // bugzilla 7302
2525 {
2526     import std.range : cycle;
2527     auto r = cycle("2A!");
2528     auto u = parse!uint(r, 16);
2529     assert(u == 42);
2530     assert(r.front == '!');
2531 }
2532 
2533 @safe pure unittest // bugzilla 13163
2534 {
2535     import std.exception;
2536     foreach (s; ["fff", "123"])
2537         assertThrown!ConvOverflowException(s.parse!ubyte(16));
2538 }
2539 
2540 @safe pure unittest // bugzilla 17282
2541 {
2542     auto str = "0=\x00\x02\x55\x40&\xff\xf0\n\x00\x04\x55\x40\xff\xf0~4+10\n";
2543     assert(parse!uint(str) == 0);
2544 }
2545 
2546 /**
2547  * Takes a string representing an `enum` type and returns that type.
2548  *
2549  * Params:
2550  *     Target = the `enum` type to convert to
2551  *     s = the lvalue of the range to _parse
2552  *
2553  * Returns:
2554  *     An `enum` of type `Target`
2555  *
2556  * Throws:
2557  *     A $(LREF ConvException) if type `Target` does not have a member
2558  *     represented by `s`.
2559  */
2560 Target parse(Target, Source)(ref Source s)
2561 if (isSomeString!Source && !is(Source == enum) &&
2562     is(Target == enum))
2563 {
2564     import std.algorithm.searching : startsWith;
2565     Target result;
2566     size_t longest_match = 0;
2567 
2568     foreach (i, e; EnumMembers!Target)
2569     {
2570         auto ident = __traits(allMembers, Target)[i];
2571         if (longest_match < ident.length && s.startsWith(ident))
2572         {
2573             result = e;
2574             longest_match = ident.length ;
2575         }
2576     }
2577 
2578     if (longest_match > 0)
2579     {
2580         s = s[longest_match .. $];
2581         return result ;
2582     }
2583 
2584     throw new ConvException(
2585         Target.stringof ~ " does not have a member named '"
2586         ~ to!string(s) ~ "'");
2587 }
2588 
2589 ///
2590 @safe unittest
2591 {
2592     enum EnumType : bool { a = true, b = false, c = a }
2593 
2594     auto str = "a";
2595     assert(parse!EnumType(str) == EnumType.a);
2596 }
2597 
2598 @safe unittest
2599 {
2600     import std.exception;
2601 
2602     enum EB : bool { a = true, b = false, c = a }
2603     enum EU { a, b, c }
2604     enum EI { a = -1, b = 0, c = 1 }
2605     enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
2606     enum EC : char { a = 'a', b = 'b', c = 'c' }
2607     enum ES : string { a = "aaa", b = "bbb", c = "ccc" }
2608 
2609     foreach (E; AliasSeq!(EB, EU, EI, EF, EC, ES))
2610     {
2611         assert(to!E("a"c) == E.a);
2612         assert(to!E("b"w) == E.b);
2613         assert(to!E("c"d) == E.c);
2614 
2615         assertThrown!ConvException(to!E("d"));
2616     }
2617 }
2618 
2619 @safe pure unittest // bugzilla 4744
2620 {
2621     enum A { member1, member11, member111 }
2622     assert(to!A("member1"  ) == A.member1  );
2623     assert(to!A("member11" ) == A.member11 );
2624     assert(to!A("member111") == A.member111);
2625     auto s = "member1111";
2626     assert(parse!A(s) == A.member111 && s == "1");
2627 }
2628 
2629 /**
2630  * Parses a character range to a floating point number.
2631  *
2632  * Params:
2633  *     Target = a floating point type
2634  *     source = the lvalue of the range to _parse
2635  *
2636  * Returns:
2637  *     A floating point number of type `Target`
2638  *
2639  * Throws:
2640  *     A $(LREF ConvException) if `p` is empty, if no number could be
2641  *     parsed, or if an overflow occurred.
2642  */
2643 Target parse(Target, Source)(ref Source source)
2644 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
2645     isFloatingPoint!Target && !is(Target == enum))
2646 {
2647     import std.ascii : isDigit, isAlpha, toLower, toUpper, isHexDigit;
2648     import std.exception : enforce;
2649 
2650     static if (isNarrowString!Source)
2651     {
2652         import std.string : representation;
2653         auto p = source.representation;
2654     }
2655     else
2656     {
2657         alias p = source;
2658     }
2659 
2660     static immutable real[14] negtab =
2661         [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L,
2662                 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ];
2663     static immutable real[13] postab =
2664         [ 1e+4096L,1e+2048L,1e+1024L,1e+512L,1e+256L,1e+128L,1e+64L,1e+32L,
2665                 1e+16L,1e+8L,1e+4L,1e+2L,1e+1L ];
2666 
bailOut()2667     ConvException bailOut()(string msg = null, string fn = __FILE__, size_t ln = __LINE__)
2668     {
2669         if (msg == null)
2670             msg = "Floating point conversion error";
2671         return new ConvException(text(msg, " for input \"", source, "\"."), fn, ln);
2672     }
2673 
2674 
2675     enforce(!p.empty, bailOut());
2676 
2677     bool sign = false;
2678     switch (p.front)
2679     {
2680     case '-':
2681         sign = true;
2682         p.popFront();
2683         enforce(!p.empty, bailOut());
2684         if (toLower(p.front) == 'i')
2685             goto case 'i';
2686         break;
2687     case '+':
2688         p.popFront();
2689         enforce(!p.empty, bailOut());
2690         break;
2691     case 'i': case 'I':
2692         // inf
2693         p.popFront();
2694         enforce(!p.empty && toUpper(p.front) == 'N',
2695                bailOut("error converting input to floating point"));
2696         p.popFront();
2697         enforce(!p.empty && toUpper(p.front) == 'F',
2698                bailOut("error converting input to floating point"));
2699         // skip past the last 'f'
2700         p.popFront();
2701         static if (isNarrowString!Source)
2702             source = cast(Source) p;
2703         return sign ? -Target.infinity : Target.infinity;
2704     default: {}
2705     }
2706 
2707     bool isHex = false;
2708     bool startsWithZero = p.front == '0';
2709     if (startsWithZero)
2710     {
2711         p.popFront();
2712         if (p.empty)
2713         {
2714             static if (isNarrowString!Source)
2715                 source = cast(Source) p;
2716             return sign ? -0.0 : 0.0;
2717         }
2718 
2719         isHex = p.front == 'x' || p.front == 'X';
2720         if (isHex) p.popFront();
2721     }
2722     else if (toLower(p.front) == 'n')
2723     {
2724         // nan
2725         p.popFront();
2726         enforce(!p.empty && toUpper(p.front) == 'A',
2727                bailOut("error converting input to floating point"));
2728         p.popFront();
2729         enforce(!p.empty && toUpper(p.front) == 'N',
2730                bailOut("error converting input to floating point"));
2731         // skip past the last 'n'
2732         p.popFront();
2733         static if (isNarrowString!Source)
2734             source = cast(Source) p;
2735         return typeof(return).nan;
2736     }
2737 
2738     /*
2739      * The following algorithm consists of 2 steps:
2740      * 1) parseDigits processes the textual input into msdec and possibly
2741      *    lsdec/msscale variables, followed by the exponent parser which sets
2742      *    exp below.
2743      *    Hex: input is 0xaaaaa...p+000... where aaaa is the mantissa in hex
2744      *    and 000 is the exponent in decimal format with base 2.
2745      *    Decimal: input is 0.00333...p+000... where 0.0033 is the mantissa
2746      *    in decimal and 000 is the exponent in decimal format with base 10.
2747      * 2) Convert msdec/lsdec and exp into native real format
2748      */
2749 
2750     real ldval = 0.0;
2751     char dot = 0;                        /* if decimal point has been seen */
2752     int exp = 0;
2753     ulong msdec = 0, lsdec = 0;
2754     ulong msscale = 1;
2755     bool sawDigits;
2756 
2757     enum { hex, decimal }
2758 
2759     // sets msdec, lsdec/msscale, and sawDigits by parsing the mantissa digits
parseDigits(alias FloatFormat)2760     void parseDigits(alias FloatFormat)()
2761     {
2762         static if (FloatFormat == hex)
2763         {
2764             enum uint base = 16;
2765             enum ulong msscaleMax = 0x1000_0000_0000_0000UL; // largest power of 16 a ulong holds
2766             enum ubyte expIter = 4; // iterate the base-2 exponent by 4 for every hex digit
2767             alias checkDigit = isHexDigit;
2768             /*
2769              * convert letter to binary representation: First clear bit
2770              * to convert lower space chars to upperspace, then -('A'-10)
2771              * converts letter A to 10, letter B to 11, ...
2772              */
2773             alias convertDigit = (int x) => isAlpha(x) ? ((x & ~0x20) - ('A' - 10)) : x - '0';
2774             sawDigits = false;
2775         }
2776         else static if (FloatFormat == decimal)
2777         {
2778             enum uint base = 10;
2779             enum ulong msscaleMax = 10_000_000_000_000_000_000UL; // largest power of 10 a ulong holds
2780             enum ubyte expIter = 1; // iterate the base-10 exponent once for every decimal digit
2781             alias checkDigit = isDigit;
2782             alias convertDigit = (int x) => x - '0';
2783             // Used to enforce that any mantissa digits are present
2784             sawDigits = startsWithZero;
2785         }
2786         else
2787             static assert(false, "Unrecognized floating-point format used.");
2788 
2789         while (!p.empty)
2790         {
2791             int i = p.front;
2792             while (checkDigit(i))
2793             {
2794                 sawDigits = true;        /* must have at least 1 digit   */
2795 
2796                 i = convertDigit(i);
2797 
2798                 if (msdec < (ulong.max - base)/base)
2799                 {
2800                     // For base 16: Y = ... + y3*16^3 + y2*16^2 + y1*16^1 + y0*16^0
2801                     msdec = msdec * base + i;
2802                 }
2803                 else if (msscale < msscaleMax)
2804                 {
2805                     lsdec = lsdec * base + i;
2806                     msscale *= base;
2807                 }
2808                 else
2809                 {
2810                     exp += expIter;
2811                 }
2812                 exp -= dot;
2813                 p.popFront();
2814                 if (p.empty)
2815                     break;
2816                 i = p.front;
2817                 if (i == '_')
2818                 {
2819                     p.popFront();
2820                     if (p.empty)
2821                         break;
2822                     i = p.front;
2823                 }
2824             }
2825             if (i == '.' && !dot)
2826             {
2827                 p.popFront();
2828                 dot += expIter;
2829             }
2830             else
2831                 break;
2832         }
2833 
2834         // Have we seen any mantissa digits so far?
2835         enforce(sawDigits, bailOut("no digits seen"));
2836         static if (FloatFormat == hex)
2837             enforce(!p.empty && (p.front == 'p' || p.front == 'P'),
2838                     bailOut("Floating point parsing: exponent is required"));
2839     }
2840 
2841     if (isHex)
2842         parseDigits!hex;
2843     else
2844         parseDigits!decimal;
2845 
2846     if (isHex || (!p.empty && (p.front == 'e' || p.front == 'E')))
2847     {
2848         char sexp = 0;
2849         int e = 0;
2850 
2851         p.popFront();
2852         enforce(!p.empty, new ConvException("Unexpected end of input"));
2853         switch (p.front)
2854         {
2855             case '-':    sexp++;
2856                          goto case;
2857             case '+':    p.popFront();
2858                          break;
2859             default: {}
2860         }
2861         sawDigits = false;
2862         while (!p.empty && isDigit(p.front))
2863         {
2864             if (e < 0x7FFFFFFF / 10 - 10)   // prevent integer overflow
2865             {
2866                 e = e * 10 + p.front - '0';
2867             }
2868             p.popFront();
2869             sawDigits = true;
2870         }
2871         exp += (sexp) ? -e : e;
2872         enforce(sawDigits, new ConvException("No digits seen."));
2873     }
2874 
2875     ldval = msdec;
2876     if (msscale != 1)               /* if stuff was accumulated in lsdec */
2877         ldval = ldval * msscale + lsdec;
2878     if (isHex)
2879     {
2880         import std.math : ldexp;
2881 
2882         // Exponent is power of 2, not power of 10
2883         ldval = ldexp(ldval,exp);
2884     }
2885     else if (ldval)
2886     {
2887         uint u = 0;
2888         int pow = 4096;
2889 
2890         while (exp > 0)
2891         {
2892             while (exp >= pow)
2893             {
2894                 ldval *= postab[u];
2895                 exp -= pow;
2896             }
2897             pow >>= 1;
2898             u++;
2899         }
2900         while (exp < 0)
2901         {
2902             while (exp <= -pow)
2903             {
2904                 ldval *= negtab[u];
2905                 enforce(ldval != 0, new ConvException("Range error"));
2906                 exp += pow;
2907             }
2908             pow >>= 1;
2909             u++;
2910         }
2911     }
2912 
2913     // if overflow occurred
2914     enforce(ldval != real.infinity, new ConvException("Range error"));
2915 
2916     static if (isNarrowString!Source)
2917         source = cast(Source) p;
2918     return sign ? -ldval : ldval;
2919 }
2920 
2921 ///
2922 @safe unittest
2923 {
2924     import std.math : approxEqual;
2925     auto str = "123.456";
2926 
2927     assert(parse!double(str).approxEqual(123.456));
2928 }
2929 
2930 @safe unittest
2931 {
2932     import std.exception;
2933     import std.math : isNaN, fabs;
2934 
2935     // Compare reals with given precision
2936     bool feq(in real rx, in real ry, in real precision = 0.000001L)
2937     {
2938         if (rx == ry)
2939             return 1;
2940 
2941         if (isNaN(rx))
2942             return cast(bool) isNaN(ry);
2943 
2944         if (isNaN(ry))
2945             return 0;
2946 
2947         return cast(bool)(fabs(rx - ry) <= precision);
2948     }
2949 
2950     // Make given typed literal
Literal(F)2951     F Literal(F)(F f)
2952     {
2953         return f;
2954     }
2955 
2956     foreach (Float; AliasSeq!(float, double, real))
2957     {
2958         assert(to!Float("123") == Literal!Float(123));
2959         assert(to!Float("+123") == Literal!Float(+123));
2960         assert(to!Float("-123") == Literal!Float(-123));
2961         assert(to!Float("123e2") == Literal!Float(123e2));
2962         assert(to!Float("123e+2") == Literal!Float(123e+2));
2963         assert(to!Float("123e-2") == Literal!Float(123e-2));
2964         assert(to!Float("123.") == Literal!Float(123.0));
2965         assert(to!Float(".375") == Literal!Float(.375));
2966 
2967         assert(to!Float("1.23375E+2") == Literal!Float(1.23375E+2));
2968 
2969         assert(to!Float("0") is 0.0);
2970         assert(to!Float("-0") is -0.0);
2971 
2972         assert(isNaN(to!Float("nan")));
2973 
2974         assertThrown!ConvException(to!Float("\x00"));
2975     }
2976 
2977     // min and max
2978     float f = to!float("1.17549e-38");
2979     assert(feq(cast(real) f, cast(real) 1.17549e-38));
2980     assert(feq(cast(real) f, cast(real) float.min_normal));
2981     f = to!float("3.40282e+38");
2982     assert(to!string(f) == to!string(3.40282e+38));
2983 
2984     // min and max
2985     double d = to!double("2.22508e-308");
2986     assert(feq(cast(real) d, cast(real) 2.22508e-308));
2987     assert(feq(cast(real) d, cast(real) double.min_normal));
2988     d = to!double("1.79769e+308");
2989     assert(to!string(d) == to!string(1.79769e+308));
2990     assert(to!string(d) == to!string(double.max));
2991 
2992     assert(to!string(to!real(to!string(real.max / 2L))) == to!string(real.max / 2L));
2993 
2994     // min and max
2995     real r = to!real(to!string(real.min_normal));
version(NetBSD)2996     version (NetBSD)
2997     {
2998         // NetBSD notice
2999         // to!string returns 3.3621e-4932L. It is less than real.min_normal and it is subnormal value
3000         // Simple C code
3001         //     long double rd = 3.3621e-4932L;
3002         //     printf("%Le\n", rd);
3003         // has unexpected result: 1.681050e-4932
3004         //
3005         // Bug report: http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=50937
3006     }
3007     else
3008     {
3009         assert(to!string(r) == to!string(real.min_normal));
3010     }
3011     r = to!real(to!string(real.max));
3012     assert(to!string(r) == to!string(real.max));
3013 }
3014 
3015 // Tests for the double implementation
3016 @system unittest
3017 {
3018     // @system because strtod is not @safe.
3019     static if (real.mant_dig == 53)
3020     {
3021         import core.stdc.stdlib, std.exception, std.math;
3022 
3023         //Should be parsed exactly: 53 bit mantissa
3024         string s = "0x1A_BCDE_F012_3456p10";
3025         auto x = parse!real(s);
3026         assert(x == 0x1A_BCDE_F012_3456p10L);
3027         //1 bit is implicit
3028         assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0xA_BCDE_F012_3456);
3029         assert(strtod("0x1ABCDEF0123456p10", null) == x);
3030 
3031         //Should be parsed exactly: 10 bit mantissa
3032         s = "0x3FFp10";
3033         x = parse!real(s);
3034         assert(x == 0x03FFp10);
3035         //1 bit is implicit
3036         assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_F800_0000_0000);
3037         assert(strtod("0x3FFp10", null) == x);
3038 
3039         //60 bit mantissa, round up
3040         s = "0xFFF_FFFF_FFFF_FFFFp10";
3041         x = parse!real(s);
3042         assert(approxEqual(x, 0xFFF_FFFF_FFFF_FFFFp10));
3043         //1 bit is implicit
3044         assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x0000_0000_0000_0000);
3045         assert(strtod("0xFFFFFFFFFFFFFFFp10", null) == x);
3046 
3047         //60 bit mantissa, round down
3048         s = "0xFFF_FFFF_FFFF_FF90p10";
3049         x = parse!real(s);
3050         assert(approxEqual(x, 0xFFF_FFFF_FFFF_FF90p10));
3051         //1 bit is implicit
3052         assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_FFFF_FFFF_FFFF);
3053         assert(strtod("0xFFFFFFFFFFFFF90p10", null) == x);
3054 
3055         //61 bit mantissa, round up 2
3056         s = "0x1F0F_FFFF_FFFF_FFFFp10";
3057         x = parse!real(s);
3058         assert(approxEqual(x, 0x1F0F_FFFF_FFFF_FFFFp10));
3059         //1 bit is implicit
3060         assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_1000_0000_0000);
3061         assert(strtod("0x1F0FFFFFFFFFFFFFp10", null) == x);
3062 
3063         //61 bit mantissa, round down 2
3064         s = "0x1F0F_FFFF_FFFF_FF10p10";
3065         x = parse!real(s);
3066         assert(approxEqual(x, 0x1F0F_FFFF_FFFF_FF10p10));
3067         //1 bit is implicit
3068         assert(((*cast(ulong*)&x) & 0x000F_FFFF_FFFF_FFFF) == 0x000F_0FFF_FFFF_FFFF);
3069         assert(strtod("0x1F0FFFFFFFFFFF10p10", null) == x);
3070 
3071         //Huge exponent
3072         s = "0x1F_FFFF_FFFF_FFFFp900";
3073         x = parse!real(s);
3074         assert(strtod("0x1FFFFFFFFFFFFFp900", null) == x);
3075 
3076         //exponent too big -> converror
3077         s = "";
3078         assertThrown!ConvException(x = parse!real(s));
3079         assert(strtod("0x1FFFFFFFFFFFFFp1024", null) == real.infinity);
3080 
3081         //-exponent too big -> 0
3082         s = "0x1FFFFFFFFFFFFFp-2000";
3083         x = parse!real(s);
3084         assert(x == 0);
3085         assert(strtod("0x1FFFFFFFFFFFFFp-2000", null) == x);
3086     }
3087 }
3088 
3089 @system unittest
3090 {
3091     import core.stdc.errno;
3092     import core.stdc.stdlib;
3093     import std.math : floatTraits, RealFormat;
3094 
3095     errno = 0;  // In case it was set by another unittest in a different module.
3096     struct longdouble
3097     {
3098         static if (floatTraits!real.realFormat == RealFormat.ieeeQuadruple)
3099         {
3100             ushort[8] value;
3101         }
3102         else static if (floatTraits!real.realFormat == RealFormat.ieeeExtended)
3103         {
3104             ushort[5] value;
3105         }
3106         else static if (floatTraits!real.realFormat == RealFormat.ieeeDouble)
3107         {
3108             ushort[4] value;
3109         }
3110         else
3111             static assert(false, "Not implemented");
3112     }
3113 
3114     real ld;
3115     longdouble x;
3116     real ld1;
3117     longdouble x1;
3118     int i;
3119 
3120     static if (floatTraits!real.realFormat == RealFormat.ieeeQuadruple)
3121         // Our parser is currently limited to ieeeExtended precision
3122         enum s = "0x1.FFFFFFFFFFFFFFFEp-16382";
3123     else static if (floatTraits!real.realFormat == RealFormat.ieeeExtended)
3124         enum s = "0x1.FFFFFFFFFFFFFFFEp-16382";
3125     else static if (floatTraits!real.realFormat == RealFormat.ieeeDouble)
3126         enum s = "0x1.FFFFFFFFFFFFFFFEp-1000";
3127     else
3128         static assert(false, "Floating point format for real not supported");
3129 
3130     auto s2 = s.idup;
3131     ld = parse!real(s2);
3132     assert(s2.empty);
3133     x = *cast(longdouble *)&ld;
3134 
3135     static if (floatTraits!real.realFormat == RealFormat.ieeeExtended)
3136     {
3137         version (CRuntime_Microsoft)
3138             ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
3139         else version (CRuntime_Bionic)
3140             ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
3141         else
3142             ld1 = strtold(s.ptr, null);
3143     }
3144     else
3145         ld1 = strtold(s.ptr, null);
3146 
3147     x1 = *cast(longdouble *)&ld1;
3148     assert(x1 == x && ld1 == ld);
3149 
3150     assert(!errno);
3151 
3152     s2 = "1.0e5";
3153     ld = parse!real(s2);
3154     assert(s2.empty);
3155     x = *cast(longdouble *)&ld;
3156     ld1 = strtold("1.0e5", null);
3157     x1 = *cast(longdouble *)&ld1;
3158 }
3159 
3160 @safe pure unittest
3161 {
3162     import std.exception;
3163 
3164     // Bugzilla 4959
3165     {
3166         auto s = "0 ";
3167         auto x = parse!double(s);
3168         assert(s == " ");
3169         assert(x == 0.0);
3170     }
3171 
3172     // Bugzilla 3369
3173     assert(to!float("inf") == float.infinity);
3174     assert(to!float("-inf") == -float.infinity);
3175 
3176     // Bugzilla 6160
3177     assert(6_5.536e3L == to!real("6_5.536e3"));                     // 2^16
3178     assert(0x1000_000_000_p10 == to!real("0x1000_000_000_p10"));    // 7.03687e+13
3179 
3180     // Bugzilla 6258
3181     assertThrown!ConvException(to!real("-"));
3182     assertThrown!ConvException(to!real("in"));
3183 
3184     // Bugzilla 7055
3185     assertThrown!ConvException(to!float("INF2"));
3186 
3187     //extra stress testing
3188     auto ssOK    = ["1.", "1.1.1", "1.e5", "2e1e", "2a", "2e1_1",
3189                     "inf", "-inf", "infa", "-infa", "inf2e2", "-inf2e2"];
3190     auto ssKO    = ["", " ", "2e", "2e+", "2e-", "2ee", "2e++1", "2e--1", "2e_1", "+inf"];
3191     foreach (s; ssOK)
3192         parse!double(s);
3193     foreach (s; ssKO)
3194         assertThrown!ConvException(parse!double(s));
3195 }
3196 
3197 /**
3198 Parsing one character off a range returns the first element and calls `popFront`.
3199 
3200 Params:
3201     Target = the type to convert to
3202     s = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3203 
3204 Returns:
3205     A character of type `Target`
3206 
3207 Throws:
3208     A $(LREF ConvException) if the range is empty.
3209  */
3210 Target parse(Target, Source)(ref Source s)
3211 if (isSomeString!Source && !is(Source == enum) &&
3212     staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0)
3213 {
3214     if (s.empty)
3215         throw convError!(Source, Target)(s);
3216     static if (is(Unqual!Target == dchar))
3217     {
3218         Target result = s.front;
3219         s.popFront();
3220         return result;
3221     }
3222     else
3223     {
3224         // Special case: okay so parse a Char off a Char[]
3225         Target result = s[0];
3226         s = s[1 .. $];
3227         return result;
3228     }
3229 }
3230 
3231 @safe pure unittest
3232 {
3233     foreach (Str; AliasSeq!(string, wstring, dstring))
3234     {
3235         foreach (Char; AliasSeq!(char, wchar, dchar))
3236         {
3237             static if (is(Unqual!Char == dchar) ||
3238                        Char.sizeof == ElementEncodingType!Str.sizeof)
3239             {
3240                 Str s = "aaa";
3241                 assert(parse!Char(s) == 'a');
3242                 assert(s == "aa");
3243             }
3244         }
3245     }
3246 }
3247 
3248 /// ditto
3249 Target parse(Target, Source)(ref Source s)
3250 if (!isSomeString!Source && isInputRange!Source && isSomeChar!(ElementType!Source) &&
3251     isSomeChar!Target && Target.sizeof >= ElementType!Source.sizeof && !is(Target == enum))
3252 {
3253     if (s.empty)
3254         throw convError!(Source, Target)(s);
3255     Target result = s.front;
3256     s.popFront();
3257     return result;
3258 }
3259 
3260 ///
3261 @safe pure unittest
3262 {
3263     auto s = "Hello, World!";
3264     char first = parse!char(s);
3265     assert(first == 'H');
3266     assert(s == "ello, World!");
3267 }
3268 
3269 
3270 /*
3271     Tests for to!bool and parse!bool
3272 */
3273 @safe pure unittest
3274 {
3275     import std.exception;
3276 
3277     assert(to!bool("TruE") == true);
3278     assert(to!bool("faLse"d) == false);
3279     assertThrown!ConvException(to!bool("maybe"));
3280 
3281     auto t = "TrueType";
3282     assert(parse!bool(t) == true);
3283     assert(t == "Type");
3284 
3285     auto f = "False killer whale"d;
3286     assert(parse!bool(f) == false);
3287     assert(f == " killer whale"d);
3288 
3289     auto m = "maybe";
3290     assertThrown!ConvException(parse!bool(m));
3291     assert(m == "maybe");  // m shouldn't change on failure
3292 
3293     auto s = "true";
3294     auto b = parse!(const(bool))(s);
3295     assert(b == true);
3296 }
3297 
3298 /**
3299 Parsing a character range to `typeof(null)` returns `null` if the range
3300 spells `"null"`. This function is case insensitive.
3301 
3302 Params:
3303     Target = the type to convert to
3304     s = the lvalue of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3305 
3306 Returns:
3307     `null`
3308 
3309 Throws:
3310     A $(LREF ConvException) if the range doesn't represent `null`.
3311  */
3312 Target parse(Target, Source)(ref Source s)
3313 if (isInputRange!Source &&
3314     isSomeChar!(ElementType!Source) &&
3315     is(Unqual!Target == typeof(null)))
3316 {
3317     import std.ascii : toLower;
3318     foreach (c; "null")
3319     {
3320         if (s.empty || toLower(s.front) != c)
3321             throw parseError("null should be case-insensitive 'null'");
3322         s.popFront();
3323     }
3324     return null;
3325 }
3326 
3327 ///
3328 @safe pure unittest
3329 {
3330     import std.exception : assertThrown;
3331 
3332     alias NullType = typeof(null);
3333     auto s1 = "null";
3334     assert(parse!NullType(s1) is null);
3335     assert(s1 == "");
3336 
3337     auto s2 = "NUll"d;
3338     assert(parse!NullType(s2) is null);
3339     assert(s2 == "");
3340 
3341     auto m = "maybe";
3342     assertThrown!ConvException(parse!NullType(m));
3343     assert(m == "maybe");  // m shouldn't change on failure
3344 
3345     auto s = "NULL";
3346     assert(parse!(const NullType)(s) is null);
3347 }
3348 
3349 //Used internally by parse Array/AA, to remove ascii whites
skipWS(R)3350 package void skipWS(R)(ref R r)
3351 {
3352     import std.ascii : isWhite;
3353     static if (isSomeString!R)
3354     {
3355         //Implementation inspired from stripLeft.
3356         foreach (i, c; r)
3357         {
3358             if (!isWhite(c))
3359             {
3360                 r = r[i .. $];
3361                 return;
3362             }
3363         }
3364         r = r[0 .. 0]; //Empty string with correct type.
3365         return;
3366     }
3367     else
3368     {
3369         for (; !r.empty && isWhite(r.front); r.popFront())
3370         {}
3371     }
3372 }
3373 
3374 /**
3375  * Parses an array from a string given the left bracket (default $(D
3376  * '[')), right bracket (default $(D ']')), and element separator (by
3377  * default $(D ',')). A trailing separator is allowed.
3378  *
3379  * Params:
3380  *     s = The string to parse
3381  *     lbracket = the character that starts the array
3382  *     rbracket = the character that ends the array
3383  *     comma = the character that separates the elements of the array
3384  *
3385  * Returns:
3386  *     An array of type `Target`
3387  */
3388 Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
3389 if (isSomeString!Source && !is(Source == enum) &&
3390     isDynamicArray!Target && !is(Target == enum))
3391 {
3392     import std.array : appender;
3393 
3394     auto result = appender!Target();
3395 
3396     parseCheck!s(lbracket);
3397     skipWS(s);
3398     if (s.empty)
3399         throw convError!(Source, Target)(s);
3400     if (s.front == rbracket)
3401     {
3402         s.popFront();
3403         return result.data;
3404     }
3405     for (;; s.popFront(), skipWS(s))
3406     {
3407         if (!s.empty && s.front == rbracket)
3408             break;
3409         result ~= parseElement!(ElementType!Target)(s);
3410         skipWS(s);
3411         if (s.empty)
3412             throw convError!(Source, Target)(s);
3413         if (s.front != comma)
3414             break;
3415     }
3416     parseCheck!s(rbracket);
3417 
3418     return result.data;
3419 }
3420 
3421 ///
3422 @safe pure unittest
3423 {
3424     auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`;
3425     auto a1 = parse!(string[])(s1);
3426     assert(a1 == ["hello", "world"]);
3427 
3428     auto s2 = `["aaa", "bbb", "ccc"]`;
3429     auto a2 = parse!(string[])(s2);
3430     assert(a2 == ["aaa", "bbb", "ccc"]);
3431 }
3432 
3433 @safe unittest // Bugzilla 9615
3434 {
3435     string s0 = "[1,2, ]";
3436     string s1 = "[1,2, \t\v\r\n]";
3437     string s2 = "[1,2]";
3438     assert(s0.parse!(int[]) == [1,2]);
3439     assert(s1.parse!(int[]) == [1,2]);
3440     assert(s2.parse!(int[]) == [1,2]);
3441 
3442     string s3 = `["a","b",]`;
3443     string s4 = `["a","b"]`;
3444     assert(s3.parse!(string[]) == ["a","b"]);
3445     assert(s4.parse!(string[]) == ["a","b"]);
3446 
3447     import std.exception : assertThrown;
3448     string s5 = "[,]";
3449     string s6 = "[, \t,]";
3450     assertThrown!ConvException(parse!(string[])(s5));
3451     assertThrown!ConvException(parse!(int[])(s6));
3452 }
3453 
3454 @safe unittest
3455 {
3456     int[] a = [1, 2, 3, 4, 5];
3457     auto s = to!string(a);
3458     assert(to!(int[])(s) == a);
3459 }
3460 
3461 @safe unittest
3462 {
3463     int[][] a = [ [1, 2] , [3], [4, 5] ];
3464     auto s = to!string(a);
3465     assert(to!(int[][])(s) == a);
3466 }
3467 
3468 @safe unittest
3469 {
3470     int[][][] ia = [ [[1,2],[3,4],[5]] , [[6],[],[7,8,9]] , [[]] ];
3471 
3472     char[] s = to!(char[])(ia);
3473     int[][][] ia2;
3474 
3475     ia2 = to!(typeof(ia2))(s);
3476     assert( ia == ia2);
3477 }
3478 
3479 @safe pure unittest
3480 {
3481     import std.exception;
3482 
3483     //Check proper failure
3484     auto s = "[ 1 , 2 , 3 ]";
3485     foreach (i ; 0 .. s.length-1)
3486     {
3487         auto ss = s[0 .. i];
3488         assertThrown!ConvException(parse!(int[])(ss));
3489     }
3490     int[] arr = parse!(int[])(s);
3491 }
3492 
3493 @safe pure unittest
3494 {
3495     //Checks parsing of strings with escaped characters
3496     string s1 = `[
3497         "Contains a\0null!",
3498         "tab\there",
3499         "line\nbreak",
3500         "backslash \\ slash / question \?",
3501         "number \x35 five",
3502         "unicode \u65E5 sun",
3503         "very long \U000065E5 sun"
3504     ]`;
3505 
3506     //Note: escaped characters purposefully replaced and isolated to guarantee
3507     //there are no typos in the escape syntax
3508     string[] s2 = [
3509         "Contains a" ~ '\0' ~ "null!",
3510         "tab" ~ '\t' ~ "here",
3511         "line" ~ '\n' ~ "break",
3512         "backslash " ~ '\\' ~ " slash / question ?",
3513         "number 5 five",
3514         "unicode 日 sun",
3515         "very long 日 sun"
3516     ];
3517     assert(s2 == parse!(string[])(s1));
3518     assert(s1.empty);
3519 }
3520 
3521 /// ditto
3522 Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
3523 if (isExactSomeString!Source &&
3524     isStaticArray!Target && !is(Target == enum))
3525 {
3526     static if (hasIndirections!Target)
3527         Target result = Target.init[0].init;
3528     else
3529         Target result = void;
3530 
3531     parseCheck!s(lbracket);
3532     skipWS(s);
3533     if (s.empty)
3534         throw convError!(Source, Target)(s);
3535     if (s.front == rbracket)
3536     {
3537         static if (result.length != 0)
3538             goto Lmanyerr;
3539         else
3540         {
3541             s.popFront();
3542             return result;
3543         }
3544     }
3545     for (size_t i = 0; ; s.popFront(), skipWS(s))
3546     {
3547         if (i == result.length)
3548             goto Lmanyerr;
3549         result[i++] = parseElement!(ElementType!Target)(s);
3550         skipWS(s);
3551         if (s.empty)
3552             throw convError!(Source, Target)(s);
3553         if (s.front != comma)
3554         {
3555             if (i != result.length)
3556                 goto Lfewerr;
3557             break;
3558         }
3559     }
3560     parseCheck!s(rbracket);
3561 
3562     return result;
3563 
3564 Lmanyerr:
3565     throw parseError(text("Too many elements in input, ", result.length, " elements expected."));
3566 
3567 Lfewerr:
3568     throw parseError(text("Too few elements in input, ", result.length, " elements expected."));
3569 }
3570 
3571 @safe pure unittest
3572 {
3573     import std.exception;
3574 
3575     auto s1 = "[1,2,3,4]";
3576     auto sa1 = parse!(int[4])(s1);
3577     assert(sa1 == [1,2,3,4]);
3578 
3579     auto s2 = "[[1],[2,3],[4]]";
3580     auto sa2 = parse!(int[][3])(s2);
3581     assert(sa2 == [[1],[2,3],[4]]);
3582 
3583     auto s3 = "[1,2,3]";
3584     assertThrown!ConvException(parse!(int[4])(s3));
3585 
3586     auto s4 = "[1,2,3,4,5]";
3587     assertThrown!ConvException(parse!(int[4])(s4));
3588 }
3589 
3590 /**
3591  * Parses an associative array from a string given the left bracket (default $(D
3592  * '[')), right bracket (default $(D ']')), key-value separator (default $(D
3593  * ':')), and element seprator (by default $(D ',')).
3594  *
3595  * Params:
3596  *     s = the string to parse
3597  *     lbracket = the character that starts the associative array
3598  *     rbracket = the character that ends the associative array
3599  *     keyval = the character that associates the key with the value
3600  *     comma = the character that separates the elements of the associative array
3601  *
3602  * Returns:
3603  *     An associative array of type `Target`
3604  */
3605 Target parse(Target, Source)(ref Source s, dchar lbracket = '[',
3606                              dchar rbracket = ']', dchar keyval = ':', dchar comma = ',')
3607 if (isSomeString!Source && !is(Source == enum) &&
3608     isAssociativeArray!Target && !is(Target == enum))
3609 {
3610     alias KeyType = typeof(Target.init.keys[0]);
3611     alias ValType = typeof(Target.init.values[0]);
3612 
3613     Target result;
3614 
3615     parseCheck!s(lbracket);
3616     skipWS(s);
3617     if (s.empty)
3618         throw convError!(Source, Target)(s);
3619     if (s.front == rbracket)
3620     {
3621         s.popFront();
3622         return result;
3623     }
3624     for (;; s.popFront(), skipWS(s))
3625     {
3626         auto key = parseElement!KeyType(s);
3627         skipWS(s);
3628         parseCheck!s(keyval);
3629         skipWS(s);
3630         auto val = parseElement!ValType(s);
3631         skipWS(s);
3632         result[key] = val;
3633         if (s.empty)
3634             throw convError!(Source, Target)(s);
3635         if (s.front != comma)
3636             break;
3637     }
3638     parseCheck!s(rbracket);
3639 
3640     return result;
3641 }
3642 
3643 ///
3644 @safe pure unittest
3645 {
3646     auto s1 = "[1:10, 2:20, 3:30]";
3647     auto aa1 = parse!(int[int])(s1);
3648     assert(aa1 == [1:10, 2:20, 3:30]);
3649 
3650     auto s2 = `["aaa":10, "bbb":20, "ccc":30]`;
3651     auto aa2 = parse!(int[string])(s2);
3652     assert(aa2 == ["aaa":10, "bbb":20, "ccc":30]);
3653 
3654     auto s3 = `["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]`;
3655     auto aa3 = parse!(int[][string])(s3);
3656     assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]);
3657 }
3658 
3659 @safe pure unittest
3660 {
3661     import std.exception;
3662 
3663     //Check proper failure
3664     auto s = "[1:10, 2:20, 3:30]";
3665     foreach (i ; 0 .. s.length-1)
3666     {
3667         auto ss = s[0 .. i];
3668         assertThrown!ConvException(parse!(int[int])(ss));
3669     }
3670     int[int] aa = parse!(int[int])(s);
3671 }
3672 
3673 private dchar parseEscape(Source)(ref Source s)
3674 if (isInputRange!Source && isSomeChar!(ElementType!Source))
3675 {
3676     parseCheck!s('\\');
3677     if (s.empty)
3678         throw parseError("Unterminated escape sequence");
3679 
getHexDigit()3680     dchar getHexDigit()(ref Source s_ = s)  // workaround
3681     {
3682         import std.ascii : isAlpha, isHexDigit;
3683         if (s_.empty)
3684             throw parseError("Unterminated escape sequence");
3685         s_.popFront();
3686         if (s_.empty)
3687             throw parseError("Unterminated escape sequence");
3688         dchar c = s_.front;
3689         if (!isHexDigit(c))
3690             throw parseError("Hex digit is missing");
3691         return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0';
3692     }
3693 
3694     dchar result;
3695 
3696     switch (s.front)
3697     {
3698         case '"':   result = '\"';  break;
3699         case '\'':  result = '\'';  break;
3700         case '0':   result = '\0';  break;
3701         case '?':   result = '\?';  break;
3702         case '\\':  result = '\\';  break;
3703         case 'a':   result = '\a';  break;
3704         case 'b':   result = '\b';  break;
3705         case 'f':   result = '\f';  break;
3706         case 'n':   result = '\n';  break;
3707         case 'r':   result = '\r';  break;
3708         case 't':   result = '\t';  break;
3709         case 'v':   result = '\v';  break;
3710         case 'x':
3711             result  = getHexDigit() << 4;
3712             result |= getHexDigit();
3713             break;
3714         case 'u':
3715             result  = getHexDigit() << 12;
3716             result |= getHexDigit() << 8;
3717             result |= getHexDigit() << 4;
3718             result |= getHexDigit();
3719             break;
3720         case 'U':
3721             result  = getHexDigit() << 28;
3722             result |= getHexDigit() << 24;
3723             result |= getHexDigit() << 20;
3724             result |= getHexDigit() << 16;
3725             result |= getHexDigit() << 12;
3726             result |= getHexDigit() << 8;
3727             result |= getHexDigit() << 4;
3728             result |= getHexDigit();
3729             break;
3730         default:
3731             throw parseError("Unknown escape character " ~ to!string(s.front));
3732     }
3733     if (s.empty)
3734         throw parseError("Unterminated escape sequence");
3735 
3736     s.popFront();
3737 
3738     return result;
3739 }
3740 
3741 @safe pure unittest
3742 {
3743     string[] s1 = [
3744         `\"`, `\'`, `\?`, `\\`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v`, //Normal escapes
3745         //`\141`, //@@@9621@@@ Octal escapes.
3746         `\x61`,
3747         `\u65E5`, `\U00012456`
3748         //`\&amp;`, `\&quot;`, //@@@9621@@@ Named Character Entities.
3749     ];
3750 
3751     const(dchar)[] s2 = [
3752         '\"', '\'', '\?', '\\', '\a', '\b', '\f', '\n', '\r', '\t', '\v', //Normal escapes
3753         //'\141', //@@@9621@@@ Octal escapes.
3754         '\x61',
3755         '\u65E5', '\U00012456'
3756         //'\&amp;', '\&quot;', //@@@9621@@@ Named Character Entities.
3757     ];
3758 
3759     foreach (i ; 0 .. s1.length)
3760     {
3761         assert(s2[i] == parseEscape(s1[i]));
3762         assert(s1[i].empty);
3763     }
3764 }
3765 
3766 @safe pure unittest
3767 {
3768     import std.exception;
3769 
3770     string[] ss = [
3771         `hello!`,  //Not an escape
3772         `\`,       //Premature termination
3773         `\/`,      //Not an escape
3774         `\gggg`,   //Not an escape
3775         `\xzz`,    //Not an hex
3776         `\x0`,     //Premature hex end
3777         `\XB9`,    //Not legal hex syntax
3778         `\u!!`,    //Not a unicode hex
3779         `\777`,    //Octal is larger than a byte //Note: Throws, but simply because octals are unsupported
3780         `\u123`,   //Premature hex end
3781         `\U123123` //Premature hex end
3782     ];
3783     foreach (s ; ss)
3784         assertThrown!ConvException(parseEscape(s));
3785 }
3786 
3787 // Undocumented
3788 Target parseElement(Target, Source)(ref Source s)
3789 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
3790     isExactSomeString!Target)
3791 {
3792     import std.array : appender;
3793     auto result = appender!Target();
3794 
3795     // parse array of chars
3796     if (s.empty)
3797         throw convError!(Source, Target)(s);
3798     if (s.front == '[')
3799         return parse!Target(s);
3800 
3801     parseCheck!s('\"');
3802     if (s.empty)
3803         throw convError!(Source, Target)(s);
3804     if (s.front == '\"')
3805     {
3806         s.popFront();
3807         return result.data;
3808     }
3809     while (true)
3810     {
3811         if (s.empty)
3812             throw parseError("Unterminated quoted string");
3813         switch (s.front)
3814         {
3815             case '\"':
3816                 s.popFront();
3817                 return result.data;
3818             case '\\':
3819                 result.put(parseEscape(s));
3820                 break;
3821             default:
3822                 result.put(s.front);
3823                 s.popFront();
3824                 break;
3825         }
3826     }
3827     assert(0);
3828 }
3829 
3830 // ditto
3831 Target parseElement(Target, Source)(ref Source s)
3832 if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) &&
3833     isSomeChar!Target && !is(Target == enum))
3834 {
3835     Target c;
3836 
3837     parseCheck!s('\'');
3838     if (s.empty)
3839         throw convError!(Source, Target)(s);
3840     if (s.front != '\\')
3841     {
3842         c = s.front;
3843         s.popFront();
3844     }
3845     else
3846         c = parseEscape(s);
3847     parseCheck!s('\'');
3848 
3849     return c;
3850 }
3851 
3852 // ditto
3853 Target parseElement(Target, Source)(ref Source s)
3854 if (isInputRange!Source && isSomeChar!(ElementType!Source) &&
3855     !isSomeString!Target && !isSomeChar!Target)
3856 {
3857     return parse!Target(s);
3858 }
3859 
3860 
3861 /***************************************************************
3862  * Convenience functions for converting one or more arguments
3863  * of any type into _text (the three character widths).
3864  */
3865 string text(T...)(T args)
3866 if (T.length > 0) { return textImpl!string(args); }
3867 
3868 ///ditto
3869 wstring wtext(T...)(T args)
3870 if (T.length > 0) { return textImpl!wstring(args); }
3871 
3872 ///ditto
3873 dstring dtext(T...)(T args)
3874 if (T.length > 0) { return textImpl!dstring(args); }
3875 
3876 ///
3877 @safe unittest
3878 {
3879     assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c);
3880     assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w);
3881     assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d);
3882 }
3883 
3884 @safe unittest
3885 {
3886     char  c = 'h';
3887     wchar w = '你';
3888     dchar d = 'እ';
3889 
3890     assert( text(c, "ello", ' ', w, "好 ", d, "ው ሰላም ነው") == "hello 你好 እው ሰላም ነው"c);
3891     assert(wtext(c, "ello", ' ', w, "好 ", d, "ው ሰላም ነው") == "hello 你好 እው ሰላም ነው"w);
3892     assert(dtext(c, "ello", ' ', w, "好 ", d, "ው ሰላም ነው") == "hello 你好 እው ሰላም ነው"d);
3893 
3894     string  cs = "今日は";
3895     wstring ws = "여보세요";
3896     dstring ds = "Здравствуйте";
3897 
3898     assert( text(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"c);
3899     assert(wtext(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"w);
3900     assert(dtext(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"d);
3901 }
3902 
3903 private S textImpl(S, U...)(U args)
3904 {
3905     static if (U.length == 0)
3906     {
3907         return null;
3908     }
3909     else static if (U.length == 1)
3910     {
3911         return to!S(args[0]);
3912     }
3913     else
3914     {
3915         import std.array : appender;
3916 
3917         auto app = appender!S();
3918 
3919         foreach (arg; args)
3920             app.put(to!S(arg));
3921         return app.data;
3922     }
3923 }
3924 
3925 
3926 /***************************************************************
3927 The $(D octal) facility provides a means to declare a number in base 8.
3928 Using $(D octal!177) or $(D octal!"177") for 127 represented in octal
3929 (same as 0177 in C).
3930 
3931 The rules for strings are the usual for literals: If it can fit in an
3932 $(D int), it is an $(D int). Otherwise, it is a $(D long). But, if the
3933 user specifically asks for a $(D long) with the $(D L) suffix, always
3934 give the $(D long). Give an unsigned iff it is asked for with the $(D
3935 U) or $(D u) suffix. _Octals created from integers preserve the type
3936 of the passed-in integral.
3937 
3938 See_Also:
3939     $(LREF parse) for parsing octal strings at runtime.
3940  */
3941 template octal(string num)
3942 if (isOctalLiteral(num))
3943 {
3944     static if ((octalFitsInInt!num && !literalIsLong!num) && !literalIsUnsigned!num)
3945         enum octal = octal!int(num);
3946     else static if ((!octalFitsInInt!num || literalIsLong!num) && !literalIsUnsigned!num)
3947         enum octal = octal!long(num);
3948     else static if ((octalFitsInInt!num && !literalIsLong!num) && literalIsUnsigned!num)
3949         enum octal = octal!uint(num);
3950     else static if ((!octalFitsInInt!(num) || literalIsLong!(num)) && literalIsUnsigned!(num))
3951         enum octal = octal!ulong(num);
3952     else
3953         static assert(false);
3954 }
3955 
3956 /// Ditto
3957 template octal(alias decimalInteger)
3958 if (isIntegral!(typeof(decimalInteger)))
3959 {
3960     enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger));
3961 }
3962 
3963 ///
3964 @safe unittest
3965 {
3966     // same as 0177
3967     auto x = octal!177;
3968     // octal is a compile-time device
3969     enum y = octal!160;
3970     // Create an unsigned octal
3971     auto z = octal!"1_000_000u";
3972 }
3973 
3974 /*
3975     Takes a string, num, which is an octal literal, and returns its
3976     value, in the type T specified.
3977 */
3978 private T octal(T)(const string num)
3979 {
3980     assert(isOctalLiteral(num));
3981 
3982     T value = 0;
3983 
3984     foreach (const char s; num)
3985     {
3986         if (s < '0' || s > '7') // we only care about digits; skip the rest
3987         // safe to skip - this is checked out in the assert so these
3988         // are just suffixes
3989             continue;
3990 
3991         value *= 8;
3992         value += s - '0';
3993     }
3994 
3995     return value;
3996 }
3997 
3998 @safe unittest
3999 {
4000     int a = octal!int("10");
4001     assert(a == 8);
4002 }
4003 
4004 /*
4005 Take a look at int.max and int.max+1 in octal and the logic for this
4006 function follows directly.
4007  */
4008 private template octalFitsInInt(string octalNum)
4009 {
4010     // note it is important to strip the literal of all
4011     // non-numbers. kill the suffix and underscores lest they mess up
4012     // the number of digits here that we depend on.
4013     enum bool octalFitsInInt = strippedOctalLiteral(octalNum).length < 11 ||
4014         strippedOctalLiteral(octalNum).length == 11 &&
4015         strippedOctalLiteral(octalNum)[0] == '1';
4016 }
4017 
4018 private string strippedOctalLiteral(string original)
4019 {
4020     string stripped = "";
4021     foreach (c; original)
4022         if (c >= '0' && c <= '7')
4023             stripped ~= c;
4024     return stripped;
4025 }
4026 
4027 private template literalIsLong(string num)
4028 {
4029     static if (num.length > 1)
4030     // can be xxL or xxLu according to spec
4031         enum literalIsLong = (num[$-1] == 'L' || num[$-2] == 'L');
4032     else
4033         enum literalIsLong = false;
4034 }
4035 
4036 private template literalIsUnsigned(string num)
4037 {
4038     static if (num.length > 1)
4039     // can be xxU or xxUL according to spec
4040         enum literalIsUnsigned = (num[$-1] == 'u' || num[$-2] == 'u')
4041             // both cases are allowed too
4042             || (num[$-1] == 'U' || num[$-2] == 'U');
4043     else
4044         enum literalIsUnsigned = false;
4045 }
4046 
4047 /*
4048 Returns if the given string is a correctly formatted octal literal.
4049 
4050 The format is specified in spec/lex.html. The leading zero is allowed, but
4051 not required.
4052  */
4053 @safe pure nothrow @nogc
4054 private bool isOctalLiteral(const string num)
4055 {
4056     if (num.length == 0)
4057         return false;
4058 
4059     // Must start with a number. To avoid confusion, literals that
4060     // start with a '0' are not allowed
4061     if (num[0] == '0' && num.length > 1)
4062         return false;
4063     if (num[0] < '0' || num[0] > '7')
4064         return false;
4065 
4066     foreach (i, c; num)
4067     {
4068         if ((c < '0' || c > '7') && c != '_') // not a legal character
4069         {
4070             if (i < num.length - 2)
4071                     return false;
4072             else   // gotta check for those suffixes
4073             {
4074                 if (c != 'U' && c != 'u' && c != 'L')
4075                         return false;
4076                 if (i != num.length - 1)
4077                 {
4078                     // if we're not the last one, the next one must
4079                     // also be a suffix to be valid
4080                     char c2 = num[$-1];
4081                     if (c2 != 'U' && c2 != 'u' && c2 != 'L')
4082                         return false; // spam at the end of the string
4083                     if (c2 == c)
4084                         return false; // repeats are disallowed
4085                 }
4086             }
4087         }
4088     }
4089 
4090     return true;
4091 }
4092 
4093 @safe unittest
4094 {
4095     // ensure that you get the right types, even with embedded underscores
4096     auto w = octal!"100_000_000_000";
4097     static assert(!is(typeof(w) == int));
4098     auto w2 = octal!"1_000_000_000";
4099     static assert(is(typeof(w2) == int));
4100 
4101     static assert(octal!"45" == 37);
4102     static assert(octal!"0" == 0);
4103     static assert(octal!"7" == 7);
4104     static assert(octal!"10" == 8);
4105     static assert(octal!"666" == 438);
4106 
4107     static assert(octal!45 == 37);
4108     static assert(octal!0 == 0);
4109     static assert(octal!7 == 7);
4110     static assert(octal!10 == 8);
4111     static assert(octal!666 == 438);
4112 
4113     static assert(octal!"66_6" == 438);
4114 
4115     static assert(octal!2520046213 == 356535435);
4116     static assert(octal!"2520046213" == 356535435);
4117 
4118     static assert(octal!17777777777 == int.max);
4119 
4120     static assert(!__traits(compiles, octal!823));
4121 
4122     static assert(!__traits(compiles, octal!"823"));
4123 
4124     static assert(!__traits(compiles, octal!"_823"));
4125     static assert(!__traits(compiles, octal!"spam"));
4126     static assert(!__traits(compiles, octal!"77%"));
4127 
4128     static assert(is(typeof(octal!"17777777777") == int));
4129     static assert(octal!"17777777777" == int.max);
4130 
4131     static assert(is(typeof(octal!"20000000000U") == ulong)); // Shouldn't this be uint?
4132     static assert(octal!"20000000000" == uint(int.max) + 1);
4133 
4134     static assert(is(typeof(octal!"777777777777777777777") == long));
4135     static assert(octal!"777777777777777777777" == long.max);
4136 
4137     static assert(is(typeof(octal!"1000000000000000000000U") == ulong));
4138     static assert(octal!"1000000000000000000000" == ulong(long.max) + 1);
4139 
4140     int a;
4141     long b;
4142 
4143     // biggest value that should fit in an it
4144     a = octal!"17777777777";
4145     assert(a == int.max);
4146     // should not fit in the int
4147     static assert(!__traits(compiles, a = octal!"20000000000"));
4148     // ... but should fit in a long
4149     b = octal!"20000000000";
4150     assert(b == 1L + int.max);
4151 
4152     b = octal!"1L";
4153     assert(b == 1);
4154     b = octal!1L;
4155     assert(b == 1);
4156 }
4157 
4158 /+
4159 emplaceRef is a package function for phobos internal use. It works like
4160 emplace, but takes its argument by ref (as opposed to "by pointer").
4161 
4162 This makes it easier to use, easier to be safe, and faster in a non-inline
4163 build.
4164 
4165 Furthermore, emplaceRef optionally takes a type paremeter, which specifies
4166 the type we want to build. This helps to build qualified objects on mutable
4167 buffer, without breaking the type system with unsafe casts.
4168 +/
4169 package void emplaceRef(T, UT, Args...)(ref UT chunk, auto ref Args args)
4170 {
4171     static if (args.length == 0)
4172     {
4173         static assert(is(typeof({static T i;})),
4174             convFormat("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof));
4175         static if (is(T == class)) static assert(!isAbstractClass!T,
4176             T.stringof ~ " is abstract and it can't be emplaced");
4177         emplaceInitializer(chunk);
4178     }
4179     else static if (
4180         !is(T == struct) && Args.length == 1 /* primitives, enums, arrays */
4181         ||
4182         Args.length == 1 && is(typeof({T t = args[0];})) /* conversions */
4183         ||
4184         is(typeof(T(args))) /* general constructors */)
4185     {
4186         static struct S
4187         {
4188             T payload;
4189             this(ref Args x)
4190             {
4191                 static if (Args.length == 1)
4192                     static if (is(typeof(payload = x[0])))
4193                         payload = x[0];
4194                     else
4195                         payload = T(x[0]);
4196                 else
4197                     payload = T(x);
4198             }
4199         }
4200         if (__ctfe)
4201         {
4202             static if (is(typeof(chunk = T(args))))
4203                 chunk = T(args);
4204             else static if (args.length == 1 && is(typeof(chunk = args[0])))
4205                 chunk = args[0];
4206             else assert(0, "CTFE emplace doesn't support "
4207                 ~ T.stringof ~ " from " ~ Args.stringof);
4208         }
4209         else
4210         {
4211             S* p = () @trusted { return cast(S*) &chunk; }();
4212             emplaceInitializer(*p);
4213             p.__ctor(args);
4214         }
4215     }
4216     else static if (is(typeof(chunk.__ctor(args))))
4217     {
4218         // This catches the rare case of local types that keep a frame pointer
4219         emplaceInitializer(chunk);
4220         chunk.__ctor(args);
4221     }
4222     else
4223     {
4224         //We can't emplace. Try to diagnose a disabled postblit.
4225         static assert(!(Args.length == 1 && is(Args[0] : T)),
4226             convFormat("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof));
4227 
4228         //We can't emplace.
4229         static assert(false,
4230             convFormat("%s cannot be emplaced from %s.", T.stringof, Args[].stringof));
4231     }
4232 }
4233 // ditto
4234 package void emplaceRef(UT, Args...)(ref UT chunk, auto ref Args args)
4235 if (is(UT == Unqual!UT))
4236 {
4237     emplaceRef!(UT, UT)(chunk, args);
4238 }
4239 
4240 //emplace helper functions
4241 private void emplaceInitializer(T)(ref T chunk) @trusted pure nothrow
4242 {
4243     static if (!hasElaborateAssign!T && isAssignable!T)
4244         chunk = T.init;
4245     else
4246     {
4247         import core.stdc.string : memcpy;
4248         static immutable T init = T.init;
4249         memcpy(&chunk, &init, T.sizeof);
4250     }
4251 }
4252 
4253 // emplace
4254 /**
4255 Given a pointer $(D chunk) to uninitialized memory (but already typed
4256 as $(D T)), constructs an object of non-$(D class) type $(D T) at that
4257 address. If `T` is a class, initializes the class reference to null.
4258 
4259 Returns: A pointer to the newly constructed object (which is the same
4260 as $(D chunk)).
4261  */
4262 T* emplace(T)(T* chunk) @safe pure nothrow
4263 {
4264     emplaceRef!T(*chunk);
4265     return chunk;
4266 }
4267 
4268 ///
4269 @system unittest
4270 {
4271     static struct S
4272     {
4273         int i = 42;
4274     }
4275     S[2] s2 = void;
4276     emplace(&s2);
4277     assert(s2[0].i == 42 && s2[1].i == 42);
4278 }
4279 
4280 ///
4281 @system unittest
4282 {
4283     interface I {}
4284     class K : I {}
4285 
4286     K k = void;
4287     emplace(&k);
4288     assert(k is null);
4289 
4290     I i = void;
4291     emplace(&i);
4292     assert(i is null);
4293 }
4294 
4295 /**
4296 Given a pointer $(D chunk) to uninitialized memory (but already typed
4297 as a non-class type $(D T)), constructs an object of type $(D T) at
4298 that address from arguments $(D args). If `T` is a class, initializes
4299 the class reference to `args[0]`.
4300 
4301 This function can be $(D @trusted) if the corresponding constructor of
4302 $(D T) is $(D @safe).
4303 
4304 Returns: A pointer to the newly constructed object (which is the same
4305 as $(D chunk)).
4306  */
4307 T* emplace(T, Args...)(T* chunk, auto ref Args args)
4308 if (is(T == struct) || Args.length == 1)
4309 {
4310     emplaceRef!T(*chunk, args);
4311     return chunk;
4312 }
4313 
4314 ///
4315 @system unittest
4316 {
4317     int a;
4318     int b = 42;
4319     assert(*emplace!int(&a, b) == 42);
4320 }
4321 
4322 @system unittest
4323 {
4324     shared int i;
4325     emplace(&i, 42);
4326     assert(i == 42);
4327 }
4328 
4329 private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName) @nogc pure nothrow
4330 {
4331     assert(chunk.length >= typeSize, "emplace: Chunk size too small.");
4332     assert((cast(size_t) chunk.ptr) % typeAlignment == 0, "emplace: Chunk is not aligned.");
4333 }
4334 
4335 /**
4336 Given a raw memory area $(D chunk), constructs an object of $(D class)
4337 type $(D T) at that address. The constructor is passed the arguments
4338 $(D Args).
4339 
4340 If `T` is an inner class whose `outer` field can be used to access an instance
4341 of the enclosing class, then `Args` must not be empty, and the first member of it
4342 must be a valid initializer for that `outer` field. Correct initialization of
4343 this field is essential to access members of the outer class inside `T` methods.
4344 
4345 Preconditions:
4346 $(D chunk) must be at least as large as $(D T) needs
4347 and should have an alignment multiple of $(D T)'s alignment. (The size
4348 of a $(D class) instance is obtained by using $(D
4349 __traits(classInstanceSize, T))).
4350 
4351 Note:
4352 This function can be $(D @trusted) if the corresponding constructor of
4353 $(D T) is $(D @safe).
4354 
4355 Returns: The newly constructed object.
4356  */
4357 T emplace(T, Args...)(void[] chunk, auto ref Args args)
4358 if (is(T == class))
4359 {
4360     static assert(!isAbstractClass!T, T.stringof ~
4361         " is abstract and it can't be emplaced");
4362 
4363     enum classSize = __traits(classInstanceSize, T);
4364     testEmplaceChunk(chunk, classSize, classInstanceAlignment!T, T.stringof);
4365     auto result = cast(T) chunk.ptr;
4366 
4367     // Initialize the object in its pre-ctor state
4368     chunk[0 .. classSize] = typeid(T).initializer[];
4369 
4370     static if (isInnerClass!T)
4371     {
4372         static assert(Args.length > 0,
4373             "Initializing an inner class requires a pointer to the outer class");
4374         static assert(is(Args[0] : typeof(T.outer)),
4375             "The first argument must be a pointer to the outer class");
4376 
4377         result.outer = args[0];
4378         alias args1 = args[1..$];
4379     }
4380     else alias args1 = args;
4381 
4382     // Call the ctor if any
4383     static if (is(typeof(result.__ctor(args1))))
4384     {
4385         // T defines a genuine constructor accepting args
4386         // Go the classic route: write .init first, then call ctor
4387         result.__ctor(args1);
4388     }
4389     else
4390     {
4391         static assert(args1.length == 0 && !is(typeof(&T.__ctor)),
4392             "Don't know how to initialize an object of type "
4393             ~ T.stringof ~ " with arguments " ~ typeof(args1).stringof);
4394     }
4395     return result;
4396 }
4397 
4398 ///
4399 @system unittest
4400 {
4401     static class C
4402     {
4403         int i;
4404         this(int i){this.i = i;}
4405     }
4406     auto buf = new void[__traits(classInstanceSize, C)];
4407     auto c = emplace!C(buf, 5);
4408     assert(c.i == 5);
4409 }
4410 
4411 @system unittest
4412 {
4413     class Outer
4414     {
4415         int i = 3;
4416         class Inner
4417         {
4418             auto getI() { return i; }
4419         }
4420     }
4421     auto outerBuf = new void[__traits(classInstanceSize, Outer)];
4422     auto innerBuf = new void[__traits(classInstanceSize, Outer.Inner)];
4423     auto inner = innerBuf.emplace!(Outer.Inner)(outerBuf.emplace!Outer);
4424     assert(inner.getI == 3);
4425 }
4426 
4427 @nogc pure nothrow @system unittest
4428 {
4429     int var = 6;
4430     align(__conv_EmplaceTestClass.alignof) ubyte[__traits(classInstanceSize, __conv_EmplaceTestClass)] buf;
4431     auto k = emplace!__conv_EmplaceTestClass(buf, 5, var);
4432     assert(k.i == 5);
4433     assert(var == 7);
4434 }
4435 
4436 /**
4437 Given a raw memory area $(D chunk), constructs an object of non-$(D
4438 class) type $(D T) at that address. The constructor is passed the
4439 arguments $(D args), if any.
4440 
4441 Preconditions:
4442 $(D chunk) must be at least as large
4443 as $(D T) needs and should have an alignment multiple of $(D T)'s
4444 alignment.
4445 
4446 Note:
4447 This function can be $(D @trusted) if the corresponding constructor of
4448 $(D T) is $(D @safe).
4449 
4450 Returns: A pointer to the newly constructed object.
4451  */
4452 T* emplace(T, Args...)(void[] chunk, auto ref Args args)
4453 if (!is(T == class))
4454 {
4455     testEmplaceChunk(chunk, T.sizeof, T.alignof, T.stringof);
4456     emplaceRef!(T, Unqual!T)(*cast(Unqual!T*) chunk.ptr, args);
4457     return cast(T*) chunk.ptr;
4458 }
4459 
4460 ///
4461 @system unittest
4462 {
4463     struct S
4464     {
4465         int a, b;
4466     }
4467     auto buf = new void[S.sizeof];
4468     S s;
4469     s.a = 42;
4470     s.b = 43;
4471     auto s1 = emplace!S(buf, s);
4472     assert(s1.a == 42 && s1.b == 43);
4473 }
4474 
4475 // Bulk of emplace unittests starts here
4476 
4477 @system unittest /* unions */
4478 {
4479     static union U
4480     {
4481         string a;
4482         int b;
4483         struct
4484         {
4485             long c;
4486             int[] d;
4487         }
4488     }
4489     U u1 = void;
4490     U u2 = { "hello" };
4491     emplace(&u1, u2);
4492     assert(u1.a == "hello");
4493 }
4494 
4495 version (unittest) private struct __conv_EmplaceTest
4496 {
4497     int i = 3;
4498     this(int i)
4499     {
4500         assert(this.i == 3 && i == 5);
4501         this.i = i;
4502     }
4503     this(int i, ref int j)
4504     {
4505         assert(i == 5 && j == 6);
4506         this.i = i;
4507         ++j;
4508     }
4509 
4510 @disable:
4511     this();
4512     this(this);
4513     void opAssign();
4514 }
4515 
4516 version (unittest) private class __conv_EmplaceTestClass
4517 {
4518     int i = 3;
4519     this(int i) @nogc @safe pure nothrow
4520     {
4521         assert(this.i == 3 && i == 5);
4522         this.i = i;
4523     }
4524     this(int i, ref int j) @nogc @safe pure nothrow
4525     {
4526         assert(i == 5 && j == 6);
4527         this.i = i;
4528         ++j;
4529     }
4530 }
4531 
4532 @system unittest // bugzilla 15772
4533 {
4534     abstract class Foo {}
4535     class Bar: Foo {}
4536     void[] memory;
4537     // test in emplaceInitializer
4538     static assert(!is(typeof(emplace!Foo(cast(Foo*) memory.ptr))));
4539     static assert( is(typeof(emplace!Bar(cast(Bar*) memory.ptr))));
4540     // test in the emplace overload that takes void[]
4541     static assert(!is(typeof(emplace!Foo(memory))));
4542     static assert( is(typeof(emplace!Bar(memory))));
4543 }
4544 
4545 @system unittest
4546 {
4547     struct S { @disable this(); }
4548     S s = void;
4549     static assert(!__traits(compiles, emplace(&s)));
4550     emplace(&s, S.init);
4551 }
4552 
4553 @system unittest
4554 {
4555     struct S1
4556     {}
4557 
4558     struct S2
4559     {
4560         void opAssign(S2);
4561     }
4562 
4563     S1 s1 = void;
4564     S2 s2 = void;
4565     S1[2] as1 = void;
4566     S2[2] as2 = void;
4567     emplace(&s1);
4568     emplace(&s2);
4569     emplace(&as1);
4570     emplace(&as2);
4571 }
4572 
4573 @system unittest
4574 {
4575     static struct S1
4576     {
4577         this(this) @disable;
4578     }
4579     static struct S2
4580     {
4581         this() @disable;
4582     }
4583     S1[2] ss1 = void;
4584     S2[2] ss2 = void;
4585     emplace(&ss1);
4586     static assert(!__traits(compiles, emplace(&ss2)));
4587     S1 s1 = S1.init;
4588     S2 s2 = S2.init;
4589     static assert(!__traits(compiles, emplace(&ss1, s1)));
4590     emplace(&ss2, s2);
4591 }
4592 
4593 @system unittest
4594 {
4595     struct S
4596     {
4597         immutable int i;
4598     }
4599     S s = void;
4600     S[2] ss1 = void;
4601     S[2] ss2 = void;
4602     emplace(&s, 5);
4603     assert(s.i == 5);
4604     emplace(&ss1, s);
4605     assert(ss1[0].i == 5 && ss1[1].i == 5);
4606     emplace(&ss2, ss1);
4607     assert(ss2 == ss1);
4608 }
4609 
4610 //Start testing emplace-args here
4611 
4612 @system unittest
4613 {
4614     interface I {}
4615     class K : I {}
4616 
4617     K k = null, k2 = new K;
4618     assert(k !is k2);
4619     emplace!K(&k, k2);
4620     assert(k is k2);
4621 
4622     I i = null;
4623     assert(i !is k);
4624     emplace!I(&i, k);
4625     assert(i is k);
4626 }
4627 
4628 @system unittest
4629 {
4630     static struct S
4631     {
4632         int i = 5;
4633         void opAssign(S){assert(0);}
4634     }
4635     S[2] sa = void;
4636     S[2] sb;
4637     emplace(&sa, sb);
4638     assert(sa[0].i == 5 && sa[1].i == 5);
4639 }
4640 
4641 //Start testing emplace-struct here
4642 
4643 // Test constructor branch
4644 @system unittest
4645 {
4646     struct S
4647     {
4648         double x = 5, y = 6;
4649         this(int a, int b)
4650         {
4651             assert(x == 5 && y == 6);
4652             x = a;
4653             y = b;
4654         }
4655     }
4656 
4657     auto s1 = new void[S.sizeof];
4658     auto s2 = S(42, 43);
4659     assert(*emplace!S(cast(S*) s1.ptr, s2) == s2);
4660     assert(*emplace!S(cast(S*) s1, 44, 45) == S(44, 45));
4661 }
4662 
4663 @system unittest
4664 {
4665     __conv_EmplaceTest k = void;
4666     emplace(&k, 5);
4667     assert(k.i == 5);
4668 }
4669 
4670 @system unittest
4671 {
4672     int var = 6;
4673     __conv_EmplaceTest k = void;
4674     emplace(&k, 5, var);
4675     assert(k.i == 5);
4676     assert(var == 7);
4677 }
4678 
4679 // Test matching fields branch
4680 @system unittest
4681 {
4682     struct S { uint n; }
4683     S s;
4684     emplace!S(&s, 2U);
4685     assert(s.n == 2);
4686 }
4687 
4688 @safe unittest
4689 {
4690     struct S { int a, b; this(int){} }
4691     S s;
4692     static assert(!__traits(compiles, emplace!S(&s, 2, 3)));
4693 }
4694 
4695 @system unittest
4696 {
4697     struct S { int a, b = 7; }
4698     S s1 = void, s2 = void;
4699 
4700     emplace!S(&s1, 2);
4701     assert(s1.a == 2 && s1.b == 7);
4702 
4703     emplace!S(&s2, 2, 3);
4704     assert(s2.a == 2 && s2.b == 3);
4705 }
4706 
4707 //opAssign
4708 @system unittest
4709 {
4710     static struct S
4711     {
4712         int i = 5;
4713         void opAssign(int){assert(0);}
4714         void opAssign(S){assert(0);}
4715     }
4716     S sa1 = void;
4717     S sa2 = void;
4718     S sb1 = S(1);
4719     emplace(&sa1, sb1);
4720     emplace(&sa2, 2);
4721     assert(sa1.i == 1);
4722     assert(sa2.i == 2);
4723 }
4724 
4725 //postblit precedence
4726 @system unittest
4727 {
4728     //Works, but breaks in "-w -O" because of @@@9332@@@.
4729     //Uncomment test when 9332 is fixed.
4730     static struct S
4731     {
4732         int i;
4733 
4734         this(S other){assert(false);}
4735         this(int i){this.i = i;}
4736         this(this){}
4737     }
4738     S a = void;
4739     assert(is(typeof({S b = a;})));    //Postblit
4740     assert(is(typeof({S b = S(a);}))); //Constructor
4741     auto b = S(5);
4742     emplace(&a, b);
4743     assert(a.i == 5);
4744 
4745     static struct S2
4746     {
4747         int* p;
4748         this(const S2){}
4749     }
4750     static assert(!is(immutable S2 : S2));
4751     S2 s2 = void;
4752     immutable is2 = (immutable S2).init;
4753     emplace(&s2, is2);
4754 }
4755 
4756 //nested structs and postblit
4757 @system unittest
4758 {
4759     static struct S
4760     {
4761         int* p;
4762         this(int i){p = [i].ptr;}
4763         this(this)
4764         {
4765             if (p)
4766                 p = [*p].ptr;
4767         }
4768     }
4769     static struct SS
4770     {
4771         S s;
4772         void opAssign(const SS)
4773         {
4774             assert(0);
4775         }
4776     }
4777     SS ssa = void;
4778     SS ssb = SS(S(5));
4779     emplace(&ssa, ssb);
4780     assert(*ssa.s.p == 5);
4781     assert(ssa.s.p != ssb.s.p);
4782 }
4783 
4784 //disabled postblit
4785 @system unittest
4786 {
4787     static struct S1
4788     {
4789         int i;
4790         @disable this(this);
4791     }
4792     S1 s1 = void;
4793     emplace(&s1, 1);
4794     assert(s1.i == 1);
4795     static assert(!__traits(compiles, emplace(&s1, S1.init)));
4796 
4797     static struct S2
4798     {
4799         int i;
4800         @disable this(this);
4801         this(ref S2){}
4802     }
4803     S2 s2 = void;
4804     static assert(!__traits(compiles, emplace(&s2, 1)));
4805     emplace(&s2, S2.init);
4806 
4807     static struct SS1
4808     {
4809         S1 s;
4810     }
4811     SS1 ss1 = void;
4812     emplace(&ss1);
4813     static assert(!__traits(compiles, emplace(&ss1, SS1.init)));
4814 
4815     static struct SS2
4816     {
4817         S2 s;
4818     }
4819     SS2 ss2 = void;
4820     emplace(&ss2);
4821     static assert(!__traits(compiles, emplace(&ss2, SS2.init)));
4822 
4823 
4824     // SS1 sss1 = s1;      //This doesn't compile
4825     // SS1 sss1 = SS1(s1); //This doesn't compile
4826     // So emplace shouldn't compile either
4827     static assert(!__traits(compiles, emplace(&sss1, s1)));
4828     static assert(!__traits(compiles, emplace(&sss2, s2)));
4829 }
4830 
4831 //Imutability
4832 @system unittest
4833 {
4834     //Castable immutability
4835     {
4836         static struct S1
4837         {
4838             int i;
4839         }
4840         static assert(is( immutable(S1) : S1));
4841         S1 sa = void;
4842         auto sb = immutable(S1)(5);
4843         emplace(&sa, sb);
4844         assert(sa.i == 5);
4845     }
4846     //Un-castable immutability
4847     {
4848         static struct S2
4849         {
4850             int* p;
4851         }
4852         static assert(!is(immutable(S2) : S2));
4853         S2 sa = void;
4854         auto sb = immutable(S2)(null);
4855         assert(!__traits(compiles, emplace(&sa, sb)));
4856     }
4857 }
4858 
4859 @system unittest
4860 {
4861     static struct S
4862     {
4863         immutable int i;
4864         immutable(int)* j;
4865     }
4866     S s = void;
4867     emplace(&s, 1, null);
4868     emplace(&s, 2, &s.i);
4869     assert(s is S(2, &s.i));
4870 }
4871 
4872 //Context pointer
4873 @system unittest
4874 {
4875     int i = 0;
4876     {
4877         struct S1
4878         {
4879             void foo(){++i;}
4880         }
4881         S1 sa = void;
4882         S1 sb;
4883         emplace(&sa, sb);
4884         sa.foo();
4885         assert(i == 1);
4886     }
4887     {
4888         struct S2
4889         {
4890             void foo(){++i;}
4891             this(this){}
4892         }
4893         S2 sa = void;
4894         S2 sb;
4895         emplace(&sa, sb);
4896         sa.foo();
4897         assert(i == 2);
4898     }
4899 }
4900 
4901 //Alias this
4902 @system unittest
4903 {
4904     static struct S
4905     {
4906         int i;
4907     }
4908     //By Ref
4909     {
4910         static struct SS1
4911         {
4912             int j;
4913             S s;
4914             alias s this;
4915         }
4916         S s = void;
4917         SS1 ss = SS1(1, S(2));
4918         emplace(&s, ss);
4919         assert(s.i == 2);
4920     }
4921     //By Value
4922     {
4923         static struct SS2
4924         {
4925             int j;
4926             S s;
4927             S foo() @property{return s;}
4928             alias foo this;
4929         }
4930         S s = void;
4931         SS2 ss = SS2(1, S(2));
4932         emplace(&s, ss);
4933         assert(s.i == 2);
4934     }
4935 }
4936 version (unittest)
4937 {
4938     //Ambiguity
4939     struct __std_conv_S
4940     {
4941         int i;
4942         this(__std_conv_SS ss)         {assert(0);}
4943         static opCall(__std_conv_SS ss)
4944         {
4945             __std_conv_S s; s.i = ss.j;
4946             return s;
4947         }
4948     }
4949     struct __std_conv_SS
4950     {
4951         int j;
4952         __std_conv_S s;
4953         ref __std_conv_S foo() return @property {s.i = j; return s;}
4954         alias foo this;
4955     }
4956     static assert(is(__std_conv_SS : __std_conv_S));
4957     @system unittest
4958     {
4959         __std_conv_S s = void;
4960         __std_conv_SS ss = __std_conv_SS(1);
4961 
4962         __std_conv_S sTest1 = ss; //this calls "SS alias this" (and not "S.this(SS)")
4963         emplace(&s, ss); //"alias this" should take precedence in emplace over "opCall"
4964         assert(s.i == 1);
4965     }
4966 }
4967 
4968 //Nested classes
4969 @system unittest
4970 {
4971     class A{}
4972     static struct S
4973     {
4974         A a;
4975     }
4976     S s1 = void;
4977     S s2 = S(new A);
4978     emplace(&s1, s2);
4979     assert(s1.a is s2.a);
4980 }
4981 
4982 //safety & nothrow & CTFE
4983 @system unittest
4984 {
4985     //emplace should be safe for anything with no elaborate opassign
4986     static struct S1
4987     {
4988         int i;
4989     }
4990     static struct S2
4991     {
4992         int i;
4993         this(int j)@safe nothrow{i = j;}
4994     }
4995 
4996     int i;
4997     S1 s1 = void;
4998     S2 s2 = void;
4999 
5000     auto pi = &i;
5001     auto ps1 = &s1;
5002     auto ps2 = &s2;
5003 
5004     void foo() @safe nothrow
5005     {
5006         emplace(pi);
5007         emplace(pi, 5);
5008         emplace(ps1);
5009         emplace(ps1, 5);
5010         emplace(ps1, S1.init);
5011         emplace(ps2);
5012         emplace(ps2, 5);
5013         emplace(ps2, S2.init);
5014     }
5015     foo();
5016 
5017     T bar(T)() @property
5018     {
5019         T t/+ = void+/; //CTFE void illegal
5020         emplace(&t, 5);
5021         return t;
5022     }
5023     // CTFE
5024     enum a = bar!int;
5025     static assert(a == 5);
5026     enum b = bar!S1;
5027     static assert(b.i == 5);
5028     enum c = bar!S2;
5029     static assert(c.i == 5);
5030     // runtime
5031     auto aa = bar!int;
5032     assert(aa == 5);
5033     auto bb = bar!S1;
5034     assert(bb.i == 5);
5035     auto cc = bar!S2;
5036     assert(cc.i == 5);
5037 }
5038 
5039 
5040 @system unittest
5041 {
5042     struct S
5043     {
5044         int[2] get(){return [1, 2];}
5045         alias get this;
5046     }
5047     struct SS
5048     {
5049         int[2] ii;
5050     }
5051     struct ISS
5052     {
5053         int[2] ii;
5054     }
5055     S s;
5056     SS ss = void;
5057     ISS iss = void;
5058     emplace(&ss, s);
5059     emplace(&iss, s);
5060     assert(ss.ii == [1, 2]);
5061     assert(iss.ii == [1, 2]);
5062 }
5063 
5064 //disable opAssign
5065 @system unittest
5066 {
5067     static struct S
5068     {
5069         @disable void opAssign(S);
5070     }
5071     S s;
5072     emplace(&s, S.init);
5073 }
5074 
5075 //opCall
5076 @system unittest
5077 {
5078     int i;
5079     //Without constructor
5080     {
5081         static struct S1
5082         {
5083             int i;
5084             static S1 opCall(int*){assert(0);}
5085         }
5086         S1 s = void;
5087         static assert(!__traits(compiles, emplace(&s,  1)));
5088     }
5089     //With constructor
5090     {
5091         static struct S2
5092         {
5093             int i = 0;
5094             static S2 opCall(int*){assert(0);}
5095             static S2 opCall(int){assert(0);}
5096             this(int i){this.i = i;}
5097         }
5098         S2 s = void;
5099         emplace(&s,  1);
5100         assert(s.i == 1);
5101     }
5102     //With postblit ambiguity
5103     {
5104         static struct S3
5105         {
5106             int i = 0;
5107             static S3 opCall(ref S3){assert(0);}
5108         }
5109         S3 s = void;
5110         emplace(&s, S3.init);
5111     }
5112 }
5113 
5114 @safe unittest //@@@9559@@@
5115 {
5116     import std.algorithm.iteration : map;
5117     import std.array : array;
5118     import std.typecons : Nullable;
5119     alias I = Nullable!int;
5120     auto ints = [0, 1, 2].map!(i => i & 1 ? I.init : I(i))();
5121     auto asArray = array(ints);
5122 }
5123 
5124 @system unittest //http://forum.dlang.org/post/nxbdgtdlmwscocbiypjs@forum.dlang.org
5125 {
5126     import std.array : array;
5127     import std.datetime : SysTime, UTC;
5128     import std.math : isNaN;
5129 
5130     static struct A
5131     {
5132         double i;
5133     }
5134 
5135     static struct B
5136     {
5137         invariant()
5138         {
5139             if (j == 0)
5140                 assert(a.i.isNaN(), "why is 'j' zero?? and i is not NaN?");
5141             else
5142                 assert(!a.i.isNaN());
5143         }
5144         SysTime when; // comment this line avoid the breakage
5145         int j;
5146         A a;
5147     }
5148 
5149     B b1 = B.init;
5150     assert(&b1); // verify that default eyes invariants are ok;
5151 
5152     auto b2 = B(SysTime(0, UTC()), 1, A(1));
5153     assert(&b2);
5154     auto b3 = B(SysTime(0, UTC()), 1, A(1));
5155     assert(&b3);
5156 
5157     auto arr = [b2, b3];
5158 
5159     assert(arr[0].j == 1);
5160     assert(arr[1].j == 1);
5161     auto a2 = arr.array(); // << bang, invariant is raised, also if b2 and b3 are good
5162 }
5163 
5164 //static arrays
5165 @system unittest
5166 {
5167     static struct S
5168     {
5169         int[2] ii;
5170     }
5171     static struct IS
5172     {
5173         immutable int[2] ii;
5174     }
5175     int[2] ii;
5176     S  s   = void;
5177     IS ims = void;
5178     ubyte ub = 2;
5179     emplace(&s, ub);
5180     emplace(&s, ii);
5181     emplace(&ims, ub);
5182     emplace(&ims, ii);
5183     uint[2] uu;
5184     static assert(!__traits(compiles, {S ss = S(uu);}));
5185     static assert(!__traits(compiles, emplace(&s, uu)));
5186 }
5187 
5188 @system unittest
5189 {
5190     int[2]  sii;
5191     int[2]  sii2;
5192     uint[2] uii;
5193     uint[2] uii2;
5194     emplace(&sii, 1);
5195     emplace(&sii, 1U);
5196     emplace(&uii, 1);
5197     emplace(&uii, 1U);
5198     emplace(&sii, sii2);
5199     //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to...
5200     //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to...
5201     emplace(&uii, uii2);
5202     emplace(&sii, sii2[]);
5203     //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to...
5204     //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to...
5205     emplace(&uii, uii2[]);
5206 }
5207 
5208 @system unittest
5209 {
5210     bool allowDestruction = false;
5211     struct S
5212     {
5213         int i;
5214         this(this){}
5215         ~this(){assert(allowDestruction);}
5216     }
5217     S s = S(1);
5218     S[2] ss1 = void;
5219     S[2] ss2 = void;
5220     S[2] ss3 = void;
5221     emplace(&ss1, s);
5222     emplace(&ss2, ss1);
5223     emplace(&ss3, ss2[]);
5224     assert(ss1[1] == s);
5225     assert(ss2[1] == s);
5226     assert(ss3[1] == s);
5227     allowDestruction = true;
5228 }
5229 
5230 @system unittest
5231 {
5232     //Checks postblit, construction, and context pointer
5233     int count = 0;
5234     struct S
5235     {
5236         this(this)
5237         {
5238             ++count;
5239         }
5240         ~this()
5241         {
5242             --count;
5243         }
5244     }
5245 
5246     S s;
5247     {
5248         S[4] ss = void;
5249         emplace(&ss, s);
5250         assert(count == 4);
5251     }
5252     assert(count == 0);
5253 }
5254 
5255 @system unittest
5256 {
5257     struct S
5258     {
5259         int i;
5260     }
5261     S s;
5262     S[2][2][2] sss = void;
5263     emplace(&sss, s);
5264 }
5265 
5266 @system unittest //Constness
5267 {
5268     import std.stdio;
5269 
5270     int a = void;
5271     emplaceRef!(const int)(a, 5);
5272 
5273     immutable i = 5;
5274     const(int)* p = void;
5275     emplaceRef!(const int*)(p, &i);
5276 
5277     struct S
5278     {
5279         int* p;
5280     }
5281     alias IS = immutable(S);
5282     S s = void;
5283     emplaceRef!IS(s, IS());
5284     S[2] ss = void;
5285     emplaceRef!(IS[2])(ss, IS());
5286 
5287     IS[2] iss = IS.init;
5288     emplaceRef!(IS[2])(ss, iss);
5289     emplaceRef!(IS[2])(ss, iss[]);
5290 }
5291 
5292 pure nothrow @safe @nogc unittest
5293 {
5294     int i;
5295     emplaceRef(i);
5296     emplaceRef!int(i);
5297     emplaceRef(i, 5);
5298     emplaceRef!int(i, 5);
5299 }
5300 
5301 // Test attribute propagation for UDTs
5302 pure nothrow @safe /* @nogc */ unittest
5303 {
5304     static struct Safe
5305     {
5306         this(this) pure nothrow @safe @nogc {}
5307     }
5308 
5309     Safe safe = void;
5310     emplaceRef(safe, Safe());
5311 
5312     Safe[1] safeArr = [Safe()];
5313     Safe[1] uninitializedSafeArr = void;
5314     emplaceRef(uninitializedSafeArr, safe);
5315     emplaceRef(uninitializedSafeArr, safeArr);
5316 
5317     static struct Unsafe
5318     {
5319         this(this) @system {}
5320     }
5321 
5322     Unsafe unsafe = void;
5323     static assert(!__traits(compiles, emplaceRef(unsafe, Unsafe())));
5324 
5325     Unsafe[1] unsafeArr = [Unsafe()];
5326     Unsafe[1] uninitializedUnsafeArr = void;
5327     static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafe)));
5328     static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafeArr)));
5329 }
5330 
5331 @system unittest
5332 {
5333     // Issue 15313
5334     static struct Node
5335     {
5336         int payload;
5337         Node* next;
5338         uint refs;
5339     }
5340 
5341     import core.stdc.stdlib : malloc;
5342     void[] buf = malloc(Node.sizeof)[0 .. Node.sizeof];
5343 
5344     import std.conv : emplace;
5345     const Node* n = emplace!(const Node)(buf, 42, null, 10);
5346     assert(n.payload == 42);
5347     assert(n.next == null);
5348     assert(n.refs == 10);
5349 }
5350 
5351 @system unittest
5352 {
5353     int var = 6;
5354     auto k = emplace!__conv_EmplaceTest(new void[__conv_EmplaceTest.sizeof], 5, var);
5355     assert(k.i == 5);
5356     assert(var == 7);
5357 }
5358 
5359 @system unittest
5360 {
5361     class A
5362     {
5363         int x = 5;
5364         int y = 42;
5365         this(int z)
5366         {
5367             assert(x == 5 && y == 42);
5368             x = y = z;
5369         }
5370     }
5371     void[] buf;
5372 
5373     static align(A.alignof) byte[__traits(classInstanceSize, A)] sbuf;
5374     buf = sbuf[];
5375     auto a = emplace!A(buf, 55);
5376     assert(a.x == 55 && a.y == 55);
5377 
5378     // emplace in bigger buffer
5379     buf = new byte[](__traits(classInstanceSize, A) + 10);
5380     a = emplace!A(buf, 55);
5381     assert(a.x == 55 && a.y == 55);
5382 
5383     // need ctor args
5384     static assert(!is(typeof(emplace!A(buf))));
5385 }
5386 // Bulk of emplace unittests ends here
5387 
5388 @safe unittest
5389 {
5390     import std.algorithm.comparison : equal;
5391     import std.algorithm.iteration : map;
5392     // Check fix for http://d.puremagic.com/issues/show_bug.cgi?id=2971
5393     assert(equal(map!(to!int)(["42", "34", "345"]), [42, 34, 345]));
5394 }
5395 
5396 // Undocumented for the time being
5397 void toTextRange(T, W)(T value, W writer)
5398 if (isIntegral!T && isOutputRange!(W, char))
5399 {
5400     import core.internal.string : SignedStringBuf, signedToTempString,
5401                                   UnsignedStringBuf, unsignedToTempString;
5402 
5403     if (value < 0)
5404     {
5405         SignedStringBuf buf = void;
5406         put(writer, signedToTempString(value, buf, 10));
5407     }
5408     else
5409     {
5410         UnsignedStringBuf buf = void;
5411         put(writer, unsignedToTempString(value, buf, 10));
5412     }
5413 }
5414 
5415 @safe unittest
5416 {
5417     import std.array : appender;
5418     auto result = appender!(char[])();
5419     toTextRange(-1, result);
5420     assert(result.data == "-1");
5421 }
5422 
5423 
5424 /**
5425     Returns the corresponding _unsigned value for $(D x) (e.g. if $(D x) has type
5426     $(D int), it returns $(D cast(uint) x)). The advantage compared to the cast
5427     is that you do not need to rewrite the cast if $(D x) later changes type
5428     (e.g from $(D int) to $(D long)).
5429 
5430     Note that the result is always mutable even if the original type was const
5431     or immutable. In order to retain the constness, use $(REF Unsigned, std,traits).
5432  */
5433 auto unsigned(T)(T x)
5434 if (isIntegral!T)
5435 {
5436     return cast(Unqual!(Unsigned!T))x;
5437 }
5438 
5439 ///
5440 @safe unittest
5441 {
5442     import std.traits : Unsigned;
5443     immutable int s = 42;
5444     auto u1 = unsigned(s); //not qualified
5445     static assert(is(typeof(u1) == uint));
5446     Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification
5447     static assert(is(typeof(u2) == immutable uint));
5448     immutable u3 = unsigned(s); //explicitly qualified
5449 }
5450 
5451 @safe unittest
5452 {
5453     foreach (T; AliasSeq!(byte, ubyte))
5454     {
5455         static assert(is(typeof(unsigned(cast(T) 1)) == ubyte));
5456         static assert(is(typeof(unsigned(cast(const T) 1)) == ubyte));
5457         static assert(is(typeof(unsigned(cast(immutable T) 1)) == ubyte));
5458     }
5459 
5460     foreach (T; AliasSeq!(short, ushort))
5461     {
5462         static assert(is(typeof(unsigned(cast(T) 1)) == ushort));
5463         static assert(is(typeof(unsigned(cast(const T) 1)) == ushort));
5464         static assert(is(typeof(unsigned(cast(immutable T) 1)) == ushort));
5465     }
5466 
5467     foreach (T; AliasSeq!(int, uint))
5468     {
5469         static assert(is(typeof(unsigned(cast(T) 1)) == uint));
5470         static assert(is(typeof(unsigned(cast(const T) 1)) == uint));
5471         static assert(is(typeof(unsigned(cast(immutable T) 1)) == uint));
5472     }
5473 
5474     foreach (T; AliasSeq!(long, ulong))
5475     {
5476         static assert(is(typeof(unsigned(cast(T) 1)) == ulong));
5477         static assert(is(typeof(unsigned(cast(const T) 1)) == ulong));
5478         static assert(is(typeof(unsigned(cast(immutable T) 1)) == ulong));
5479     }
5480 }
5481 
5482 auto unsigned(T)(T x)
5483 if (isSomeChar!T)
5484 {
5485     // All characters are unsigned
5486     static assert(T.min == 0);
5487     return cast(Unqual!T) x;
5488 }
5489 
5490 @safe unittest
5491 {
5492     foreach (T; AliasSeq!(char, wchar, dchar))
5493     {
5494         static assert(is(typeof(unsigned(cast(T)'A')) == T));
5495         static assert(is(typeof(unsigned(cast(const T)'A')) == T));
5496         static assert(is(typeof(unsigned(cast(immutable T)'A')) == T));
5497     }
5498 }
5499 
5500 
5501 /**
5502     Returns the corresponding _signed value for $(D x) (e.g. if $(D x) has type
5503     $(D uint), it returns $(D cast(int) x)). The advantage compared to the cast
5504     is that you do not need to rewrite the cast if $(D x) later changes type
5505     (e.g from $(D uint) to $(D ulong)).
5506 
5507     Note that the result is always mutable even if the original type was const
5508     or immutable. In order to retain the constness, use $(REF Signed, std,traits).
5509  */
5510 auto signed(T)(T x)
5511 if (isIntegral!T)
5512 {
5513     return cast(Unqual!(Signed!T))x;
5514 }
5515 
5516 ///
5517 @safe unittest
5518 {
5519     import std.traits : Signed;
5520 
5521     immutable uint u = 42;
5522     auto s1 = signed(u); //not qualified
5523     static assert(is(typeof(s1) == int));
5524     Signed!(typeof(u)) s2 = signed(u); //same qualification
5525     static assert(is(typeof(s2) == immutable int));
5526     immutable s3 = signed(u); //explicitly qualified
5527 }
5528 
5529 @system unittest
5530 {
5531     foreach (T; AliasSeq!(byte, ubyte))
5532     {
5533         static assert(is(typeof(signed(cast(T) 1)) == byte));
5534         static assert(is(typeof(signed(cast(const T) 1)) == byte));
5535         static assert(is(typeof(signed(cast(immutable T) 1)) == byte));
5536     }
5537 
5538     foreach (T; AliasSeq!(short, ushort))
5539     {
5540         static assert(is(typeof(signed(cast(T) 1)) == short));
5541         static assert(is(typeof(signed(cast(const T) 1)) == short));
5542         static assert(is(typeof(signed(cast(immutable T) 1)) == short));
5543     }
5544 
5545     foreach (T; AliasSeq!(int, uint))
5546     {
5547         static assert(is(typeof(signed(cast(T) 1)) == int));
5548         static assert(is(typeof(signed(cast(const T) 1)) == int));
5549         static assert(is(typeof(signed(cast(immutable T) 1)) == int));
5550     }
5551 
5552     foreach (T; AliasSeq!(long, ulong))
5553     {
5554         static assert(is(typeof(signed(cast(T) 1)) == long));
5555         static assert(is(typeof(signed(cast(const T) 1)) == long));
5556         static assert(is(typeof(signed(cast(immutable T) 1)) == long));
5557     }
5558 }
5559 
5560 @safe unittest
5561 {
5562     // issue 10874
5563     enum Test { a = 0 }
5564     ulong l = 0;
5565     auto t = l.to!Test;
5566 }
5567 
5568 // asOriginalType
5569 /**
5570 Returns the representation of an enumerated value, i.e. the value converted to
5571 the base type of the enumeration.
5572 */
5573 OriginalType!E asOriginalType(E)(E value) if (is(E == enum))
5574 {
5575     return value;
5576 }
5577 
5578 ///
5579 @safe unittest
5580 {
5581     enum A { a = 42 }
5582     static assert(is(typeof(A.a.asOriginalType) == int));
5583     assert(A.a.asOriginalType == 42);
5584     enum B : double { a = 43 }
5585     static assert(is(typeof(B.a.asOriginalType) == double));
5586     assert(B.a.asOriginalType == 43);
5587 }
5588 
5589 /**
5590     A wrapper on top of the built-in cast operator that allows one to restrict
5591     casting of the original type of the value.
5592 
5593     A common issue with using a raw cast is that it may silently continue to
5594     compile even if the value's type has changed during refactoring,
5595     which breaks the initial assumption about the cast.
5596 
5597     Params:
5598         From  = The type to cast from. The programmer must ensure it is legal
5599                 to make this cast.
5600  */
5601 template castFrom(From)
5602 {
5603     /**
5604         Params:
5605             To    = The type _to cast _to.
5606             value = The value _to cast. It must be of type $(D From),
5607                     otherwise a compile-time error is emitted.
5608 
5609         Returns:
5610             the value after the cast, returned by reference if possible.
5611      */
5612     auto ref to(To, T)(auto ref T value) @system
5613     {
5614         static assert(
5615             is(From == T),
5616             "the value to cast is not of specified type '" ~ From.stringof ~
5617                  "', it is of type '" ~ T.stringof ~ "'"
5618         );
5619 
5620         static assert(
5621             is(typeof(cast(To) value)),
5622             "can't cast from '" ~ From.stringof ~ "' to '" ~ To.stringof ~ "'"
5623         );
5624 
5625         return cast(To) value;
5626     }
5627 }
5628 
5629 ///
5630 @system unittest
5631 {
5632     // Regular cast, which has been verified to be legal by the programmer:
5633     {
5634         long x;
5635         auto y = cast(int) x;
5636     }
5637 
5638     // However this will still compile if 'x' is changed to be a pointer:
5639     {
5640         long* x;
5641         auto y = cast(int) x;
5642     }
5643 
5644     // castFrom provides a more reliable alternative to casting:
5645     {
5646         long x;
5647         auto y = castFrom!long.to!int(x);
5648     }
5649 
5650     // Changing the type of 'x' will now issue a compiler error,
5651     // allowing bad casts to be caught before it's too late:
5652     {
5653         long* x;
5654         static assert(
5655             !__traits(compiles, castFrom!long.to!int(x))
5656         );
5657 
5658         // if cast is still needed, must be changed to:
5659         auto y = castFrom!(long*).to!int(x);
5660     }
5661 }
5662 
5663 // https://issues.dlang.org/show_bug.cgi?id=16667
5664 @system unittest
5665 {
5666     ubyte[] a = ['a', 'b', 'c'];
5667     assert(castFrom!(ubyte[]).to!(string)(a) == "abc");
5668 }
5669 
5670 /**
5671 Check the correctness of a string for $(D hexString).
5672 The result is true if and only if the input string is composed of whitespace
5673 characters (\f\n\r\t\v lineSep paraSep nelSep) and
5674 an even number of hexadecimal digits (regardless of the case).
5675 */
5676 @safe pure @nogc
5677 private bool isHexLiteral(String)(scope const String hexData)
5678 {
5679     import std.ascii : isHexDigit;
5680     import std.uni : lineSep, paraSep, nelSep;
5681     size_t i;
5682     foreach (const dchar c; hexData)
5683     {
5684         switch (c)
5685         {
5686             case ' ':
5687             case '\t':
5688             case '\v':
5689             case '\f':
5690             case '\r':
5691             case '\n':
5692             case lineSep:
5693             case paraSep:
5694             case nelSep:
5695                 continue;
5696 
5697             default:
5698                 break;
5699         }
5700         if (c.isHexDigit)
5701             ++i;
5702         else
5703             return false;
5704     }
5705     return !(i & 1);
5706 }
5707 
5708 @safe unittest
5709 {
5710     // test all the hex digits
5711     static assert( ("0123456789abcdefABCDEF").isHexLiteral);
5712     // empty or white strings are not valid
5713     static assert( "\r\n\t".isHexLiteral);
5714     // but are accepted if the count of hex digits is even
5715     static assert( "A\r\n\tB".isHexLiteral);
5716 }
5717 
5718 @safe unittest
5719 {
5720     import std.ascii;
5721     // empty/whites
5722     static assert( "".isHexLiteral);
5723     static assert( " \r".isHexLiteral);
5724     static assert( whitespace.isHexLiteral);
5725     static assert( ""w.isHexLiteral);
5726     static assert( " \r"w.isHexLiteral);
5727     static assert( ""d.isHexLiteral);
5728     static assert( " \r"d.isHexLiteral);
5729     static assert( "\u2028\u2029\u0085"d.isHexLiteral);
5730     // odd x strings
5731     static assert( !("5" ~ whitespace).isHexLiteral);
5732     static assert( !"123".isHexLiteral);
5733     static assert( !"1A3".isHexLiteral);
5734     static assert( !"1 23".isHexLiteral);
5735     static assert( !"\r\n\tC".isHexLiteral);
5736     static assert( !"123"w.isHexLiteral);
5737     static assert( !"1A3"w.isHexLiteral);
5738     static assert( !"1 23"w.isHexLiteral);
5739     static assert( !"\r\n\tC"w.isHexLiteral);
5740     static assert( !"123"d.isHexLiteral);
5741     static assert( !"1A3"d.isHexLiteral);
5742     static assert( !"1 23"d.isHexLiteral);
5743     static assert( !"\r\n\tC"d.isHexLiteral);
5744     // even x strings with invalid charset
5745     static assert( !"12gG".isHexLiteral);
5746     static assert( !"2A  3q".isHexLiteral);
5747     static assert( !"12gG"w.isHexLiteral);
5748     static assert( !"2A  3q"w.isHexLiteral);
5749     static assert( !"12gG"d.isHexLiteral);
5750     static assert( !"2A  3q"d.isHexLiteral);
5751     // valid x strings
5752     static assert( ("5A" ~ whitespace).isHexLiteral);
5753     static assert( ("5A 01A C FF de 1b").isHexLiteral);
5754     static assert( ("0123456789abcdefABCDEF").isHexLiteral);
5755     static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF").isHexLiteral);
5756     static assert( ("5A 01A C FF de 1b"w).isHexLiteral);
5757     static assert( ("0123456789abcdefABCDEF"w).isHexLiteral);
5758     static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"w).isHexLiteral);
5759     static assert( ("5A 01A C FF de 1b"d).isHexLiteral);
5760     static assert( ("0123456789abcdefABCDEF"d).isHexLiteral);
5761     static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"d).isHexLiteral);
5762     // library version allows what's pointed by issue 10454
5763     static assert( ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").isHexLiteral);
5764 }
5765 
5766 /**
5767 Converts a hex literal to a string at compile time.
5768 
5769 Takes a string made of hexadecimal digits and returns
5770 the matching string by converting each pair of digits to a character.
5771 The input string can also include white characters, which can be used
5772 to keep the literal string readable in the source code.
5773 
5774 The function is intended to replace the hexadecimal literal strings
5775 starting with $(D 'x'), which could be removed to simplify the core language.
5776 
5777 Params:
5778     hexData = string to be converted.
5779 
5780 Returns:
5781     a $(D string), a $(D wstring) or a $(D dstring), according to the type of hexData.
5782  */
5783 template hexString(string hexData)
5784 if (hexData.isHexLiteral)
5785 {
5786     immutable hexString = hexStrImpl(hexData);
5787 }
5788 
5789 /// ditto
5790 template hexString(wstring hexData)
5791 if (hexData.isHexLiteral)
5792 {
5793     immutable hexString = hexStrImpl(hexData);
5794 }
5795 
5796 /// ditto
5797 template hexString(dstring hexData)
5798 if (hexData.isHexLiteral)
5799 {
5800     immutable hexString = hexStrImpl(hexData);
5801 }
5802 
5803 ///
5804 @safe unittest
5805 {
5806     // conversion at compile time
5807     auto string1 = hexString!"304A314B";
5808     assert(string1 == "0J1K");
5809     auto string2 = hexString!"304A314B"w;
5810     assert(string2 == "0J1K"w);
5811     auto string3 = hexString!"304A314B"d;
5812     assert(string3 == "0J1K"d);
5813 }
5814 
5815 /*
5816     Takes a hexadecimal string literal and returns its representation.
5817     hexData is granted to be a valid string by the caller.
5818     C is granted to be a valid char type by the caller.
5819 */
5820 @safe nothrow pure
5821 private auto hexStrImpl(String)(scope String hexData)
5822 {
5823     import std.ascii : isHexDigit;
5824     alias C = Unqual!(ElementEncodingType!String);
5825     C[] result;
5826     result.length = hexData.length / 2;
5827     size_t cnt;
5828     ubyte v;
5829     foreach (c; hexData)
5830     {
5831         if (c.isHexDigit)
5832         {
5833             ubyte x;
5834             if (c >= '0' && c <= '9')
5835                 x = cast(ubyte)(c - '0');
5836             else if (c >= 'a' && c <= 'f')
5837                 x = cast(ubyte)(c - ('a' - 10));
5838             else if (c >= 'A' && c <= 'F')
5839                 x = cast(ubyte)(c - ('A' - 10));
5840             if (cnt & 1)
5841             {
5842                 v = cast(ubyte)((v << 4) | x);
5843                 result[cnt / 2] = v;
5844             }
5845             else
5846                 v = x;
5847             ++cnt;
5848         }
5849     }
5850     result.length = cnt / 2;
5851     return result;
5852 }
5853 
5854 @safe unittest
5855 {
5856     // compile time
5857     assert(hexString!"46 47 48 49 4A 4B" == "FGHIJK");
5858     assert(hexString!"30\r\n\t\f\v31 32 33 32 31 30" == "0123210");
5859     assert(hexString!"ab cd" == hexString!"ABCD");
5860 }
5861 
5862 
5863 /**
5864  * Convert integer to a range of characters.
5865  * Intended to be lightweight and fast.
5866  *
5867  * Params:
5868  *      radix = 2, 8, 10, 16
5869  *      Char = character type for output
5870  *      letterCase = lower for deadbeef, upper for DEADBEEF
5871  *      value = integer to convert. Can be uint or ulong. If radix is 10, can also be
5872  *              int or long.
5873  * Returns:
5874  *      Random access range with slicing and everything
5875  */
5876 
5877 auto toChars(ubyte radix = 10, Char = char, LetterCase letterCase = LetterCase.lower, T)(T value)
5878     pure nothrow @nogc @safe
5879 if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
5880     (is(Unqual!T == uint) || is(Unqual!T == ulong) ||
5881     radix == 10 && (is(Unqual!T == int) || is(Unqual!T == long))))
5882 {
5883     alias UT = Unqual!T;
5884 
5885     static if (radix == 10)
5886     {
5887         /* uint.max  is 42_9496_7295
5888          *  int.max  is 21_4748_3647
5889          * ulong.max is 1844_6744_0737_0955_1615
5890          *  long.max is  922_3372_0368_5477_5807
5891          */
5892         static struct Result
5893         {
5894             void initialize(UT value)
5895             {
5896                 bool neg = false;
5897                 if (value < 10)
5898                 {
5899                     if (value >= 0)
5900                     {
5901                         lwr = 0;
5902                         upr = 1;
5903                         buf[0] = cast(char)(cast(uint) value + '0');
5904                         return;
5905                     }
5906                     value = -value;
5907                     neg = true;
5908                 }
5909                 auto i = cast(uint) buf.length - 1;
5910                 while (cast(Unsigned!UT) value >= 10)
5911                 {
5912                     buf[i] = cast(ubyte)('0' + cast(Unsigned!UT) value % 10);
5913                     value = unsigned(value) / 10;
5914                     --i;
5915                 }
5916                 buf[i] = cast(char)(cast(uint) value + '0');
5917                 if (neg)
5918                 {
5919                     buf[i - 1] = '-';
5920                     --i;
5921                 }
5922                 lwr = i;
5923                 upr = cast(uint) buf.length;
5924             }
5925 
5926             @property size_t length() { return upr - lwr; }
5927 
5928             alias opDollar = length;
5929 
5930             @property bool empty() { return upr == lwr; }
5931 
5932             @property Char front() { return buf[lwr]; }
5933 
5934             void popFront() { ++lwr; }
5935 
5936             @property Char back() { return buf[upr - 1]; }
5937 
5938             void popBack() { --upr; }
5939 
5940             @property Result save() { return this; }
5941 
5942             Char opIndex(size_t i) { return buf[lwr + i]; }
5943 
5944             Result opSlice(size_t lwr, size_t upr)
5945             {
5946                 Result result = void;
5947                 result.buf = buf;
5948                 result.lwr = cast(uint)(this.lwr + lwr);
5949                 result.upr = cast(uint)(this.lwr + upr);
5950                 return result;
5951             }
5952 
5953           private:
5954             uint lwr = void, upr = void;
5955             char[(UT.sizeof == 4) ? 10 + isSigned!T : 20] buf = void;
5956         }
5957 
5958         Result result = void;
5959         result.initialize(value);
5960         return result;
5961     }
5962     else
5963     {
5964         static if (radix == 2)
5965             enum SHIFT = 1;
5966         else static if (radix == 8)
5967             enum SHIFT = 3;
5968         else static if (radix == 16)
5969             enum SHIFT = 4;
5970         else
5971             static assert(0);
5972         static struct Result
5973         {
5974             this(UT value)
5975             {
5976                 this.value = value;
5977 
5978                 ubyte len = 1;
5979                 while (value >>>= SHIFT)
5980                    ++len;
5981                 this.len = len;
5982             }
5983 
5984             @property size_t length() { return len; }
5985 
5986             @property bool empty() { return len == 0; }
5987 
5988             @property Char front() { return opIndex(0); }
5989 
5990             void popFront() { --len; }
5991 
5992             @property Char back() { return opIndex(len - 1); }
5993 
5994             void popBack()
5995             {
5996                 value >>>= SHIFT;
5997                 --len;
5998             }
5999 
6000             @property Result save() { return this; }
6001 
6002             Char opIndex(size_t i)
6003             {
6004                 Char c = (value >>> ((len - i - 1) * SHIFT)) & ((1 << SHIFT) - 1);
6005                 return cast(Char)((radix < 10 || c < 10) ? c + '0'
6006                                                          : (letterCase == LetterCase.upper ? c + 'A' - 10
6007                                                                                            : c + 'a' - 10));
6008             }
6009 
6010             Result opSlice(size_t lwr, size_t upr)
6011             {
6012                 Result result = void;
6013                 result.value = value >>> ((len - upr) * SHIFT);
6014                 result.len = cast(ubyte)(upr - lwr);
6015                 return result;
6016             }
6017 
6018           private:
6019             UT value;
6020             ubyte len;
6021         }
6022 
6023         return Result(value);
6024     }
6025 }
6026 
6027 
6028 @safe unittest
6029 {
6030     import std.array;
6031     import std.range;
6032 
6033     {
6034         assert(toChars!2(0u).array == "0");
6035         assert(toChars!2(0Lu).array == "0");
6036         assert(toChars!2(1u).array == "1");
6037         assert(toChars!2(1Lu).array == "1");
6038 
6039         auto r = toChars!2(2u);
6040         assert(r.length == 2);
6041         assert(r[0] == '1');
6042         assert(r[1 .. 2].array == "0");
6043         auto s = r.save;
6044         assert(r.array == "10");
6045         assert(s.retro.array == "01");
6046     }
6047     {
6048         assert(toChars!8(0u).array == "0");
6049         assert(toChars!8(0Lu).array == "0");
6050         assert(toChars!8(1u).array == "1");
6051         assert(toChars!8(1234567Lu).array == "4553207");
6052 
6053         auto r = toChars!8(8u);
6054         assert(r.length == 2);
6055         assert(r[0] == '1');
6056         assert(r[1 .. 2].array == "0");
6057         auto s = r.save;
6058         assert(r.array == "10");
6059         assert(s.retro.array == "01");
6060     }
6061     {
6062         assert(toChars!10(0u).array == "0");
6063         assert(toChars!10(0Lu).array == "0");
6064         assert(toChars!10(1u).array == "1");
6065         assert(toChars!10(1234567Lu).array == "1234567");
6066         assert(toChars!10(uint.max).array == "4294967295");
6067         assert(toChars!10(ulong.max).array == "18446744073709551615");
6068 
6069         auto r = toChars(10u);
6070         assert(r.length == 2);
6071         assert(r[0] == '1');
6072         assert(r[1 .. 2].array == "0");
6073         auto s = r.save;
6074         assert(r.array == "10");
6075         assert(s.retro.array == "01");
6076     }
6077     {
6078         assert(toChars!10(0).array == "0");
6079         assert(toChars!10(0L).array == "0");
6080         assert(toChars!10(1).array == "1");
6081         assert(toChars!10(1234567L).array == "1234567");
6082         assert(toChars!10(int.max).array == "2147483647");
6083         assert(toChars!10(long.max).array == "9223372036854775807");
6084         assert(toChars!10(-int.max).array == "-2147483647");
6085         assert(toChars!10(-long.max).array == "-9223372036854775807");
6086         assert(toChars!10(int.min).array == "-2147483648");
6087         assert(toChars!10(long.min).array == "-9223372036854775808");
6088 
6089         auto r = toChars!10(10);
6090         assert(r.length == 2);
6091         assert(r[0] == '1');
6092         assert(r[1 .. 2].array == "0");
6093         auto s = r.save;
6094         assert(r.array == "10");
6095         assert(s.retro.array == "01");
6096     }
6097     {
6098         assert(toChars!(16)(0u).array == "0");
6099         assert(toChars!(16)(0Lu).array == "0");
6100         assert(toChars!(16)(10u).array == "a");
6101         assert(toChars!(16, char, LetterCase.upper)(0x12AF34567Lu).array == "12AF34567");
6102 
6103         auto r = toChars!(16)(16u);
6104         assert(r.length == 2);
6105         assert(r[0] == '1');
6106         assert(r[1 .. 2].array == "0");
6107         auto s = r.save;
6108         assert(r.array == "10");
6109         assert(s.retro.array == "01");
6110     }
6111 }
6112 
6113 @safe unittest // opSlice (issue 16192)
6114 {
6115     import std.meta : AliasSeq;
6116 
6117     static struct Test { ubyte radix; uint number; }
6118 
6119     alias tests = AliasSeq!(
6120         Test(2, 0b1_0110_0111u),
6121         Test(2, 0b10_1100_1110u),
6122         Test(8, octal!123456701u),
6123         Test(8, octal!1234567012u),
6124         Test(10, 123456789u),
6125         Test(10, 1234567890u),
6126         Test(16, 0x789ABCDu),
6127         Test(16, 0x789ABCDEu),
6128     );
6129 
6130     foreach (test; tests)
6131     {
6132         enum ubyte radix = test.radix;
6133         auto original = toChars!radix(test.number);
6134 
6135         // opSlice vs popFront
6136         auto r = original.save;
6137         size_t i = 0;
6138         for (; !r.empty; r.popFront(), ++i)
6139         {
6140             assert(original[i .. original.length].tupleof == r.tupleof);
6141                 // tupleof is used to work around issue 16216.
6142         }
6143 
6144         // opSlice vs popBack
6145         r = original.save;
6146         i = 0;
6147         for (; !r.empty; r.popBack(), ++i)
6148         {
6149             assert(original[0 .. original.length - i].tupleof == r.tupleof);
6150         }
6151 
6152         // opSlice vs both popFront and popBack
6153         r = original.save;
6154         i = 0;
6155         for (; r.length >= 2; r.popFront(), r.popBack(), ++i)
6156         {
6157             assert(original[i .. original.length - i].tupleof == r.tupleof);
6158         }
6159     }
6160 }
6161