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