@safe unittest { import std.conv; import std.exception : assertThrown; assertThrown!ConvException(to!int("abc")); } @safe unittest { import std.conv; import std.exception : assertThrown; assertThrown!ConvOverflowException(to!ubyte(1_000_000)); } @safe pure unittest { import std.conv; int a = 42; int b = to!int(a); double c = to!double(3.14); // c is double with value 3.14 } @safe pure unittest { import std.conv; import std.exception : assertThrown; int a = 420; assert(to!long(a) == a); assertThrown!ConvOverflowException(to!byte(a)); assert(to!int(4.2e6) == 4200000); assertThrown!ConvOverflowException(to!uint(-3.14)); assert(to!uint(3.14) == 3); assert(to!uint(3.99) == 3); assert(to!int(-3.99) == -3); } @safe pure unittest { import std.conv; auto str = to!string(42, 16); assert(str == "2A"); auto i = to!int(str, 16); assert(i == 42); } @safe pure unittest { import std.conv; // 2^24 - 1, largest proper integer representable as float int a = 16_777_215; assert(to!int(to!float(a)) == a); assert(to!int(to!float(-a)) == -a); } @safe pure unittest { import std.conv; import std.exception : assertThrown; assert(to!char("a") == 'a'); assertThrown(to!char("ñ")); // 'ñ' does not fit into a char assert(to!wchar("ñ") == 'ñ'); assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar assert(to!dchar("😃") == '😃'); // Using wstring or dstring as source type does not affect the result assert(to!char("a"w) == 'a'); assert(to!char("a"d) == 'a'); // Two code points cannot be converted to a single one assertThrown(to!char("ab")); } @safe pure unittest { import std.conv; import std.string : split; int[] a = [1, 2, 3]; auto b = to!(float[])(a); assert(b == [1.0f, 2, 3]); string str = "1 2 3 4 5 6"; auto numbers = to!(double[])(split(str)); assert(numbers == [1.0, 2, 3, 4, 5, 6]); int[string] c; c["a"] = 1; c["b"] = 2; auto d = to!(double[wstring])(c); assert(d["a"w] == 1 && d["b"w] == 2); } @safe unittest { import std.conv; int[string][double[int[]]] a; auto b = to!(short[wstring][string[double[]]])(a); } @safe pure unittest { import std.conv; import std.exception : assertThrown; // Testing object conversions class A {} class B : A {} class C : A {} A a1 = new A, a2 = new B, a3 = new C; assert(to!B(a2) is a2); assert(to!C(a3) is a3); assertThrown!ConvException(to!B(a3)); } @system pure unittest { import std.conv; // Conversion representing dynamic/static array with string long[] a = [ 1, 3, 5 ]; assert(to!string(a) == "[1, 3, 5]"); // Conversion representing associative array with string int[string] associativeArray = ["0":1, "1":2]; assert(to!string(associativeArray) == `["0":1, "1":2]` || to!string(associativeArray) == `["1":2, "0":1]`); // char* to string conversion assert(to!string(cast(char*) null) == ""); assert(to!string("foo\0".ptr) == "foo"); // Conversion reinterpreting void array to string auto w = "abcx"w; const(void)[] b = w; assert(b.length == 8); auto c = to!(wchar[])(b); assert(c == "abcx"); } @safe pure unittest { import std.conv; import std.exception : assertThrown; enum E { a, b, c } assert(to!E("a") == E.a); assert(to!E("b") == E.b); assertThrown!ConvException(to!E("A")); } @safe unittest { import std.conv; assert(roundTo!int(3.14) == 3); assert(roundTo!int(3.49) == 3); assert(roundTo!int(3.5) == 4); assert(roundTo!int(3.999) == 4); assert(roundTo!int(-3.14) == -3); assert(roundTo!int(-3.49) == -3); assert(roundTo!int(-3.5) == -4); assert(roundTo!int(-3.999) == -4); assert(roundTo!(const int)(to!(const double)(-3.999)) == -4); } @safe unittest { import std.conv; import std.typecons : Flag, Yes, No; auto s = "true"; bool b = parse!bool(s); assert(b); auto s2 = "true"; bool b2 = parse!(bool, string, No.doCount)(s2); assert(b2); auto s3 = "true"; auto b3 = parse!(bool, string, Yes.doCount)(s3); assert(b3.data && b3.count == 4); auto s4 = "falSE"; auto b4 = parse!(bool, string, Yes.doCount)(s4); assert(!b4.data && b4.count == 5); } @safe pure unittest { import std.conv; import std.typecons : Flag, Yes, No; string s = "123"; auto a = parse!int(s); assert(a == 123); string s1 = "123"; auto a1 = parse!(int, string, Yes.doCount)(s1); assert(a1.data == 123 && a1.count == 3); } @safe pure unittest { import std.conv; import std.string : tr; import std.typecons : Flag, Yes, No; string test = "123 \t 76.14"; auto a = parse!uint(test); assert(a == 123); assert(test == " \t 76.14"); // parse bumps string test = tr(test, " \t\n\r", "", "d"); // skip ws assert(test == "76.14"); auto b = parse!double(test); assert(b == 76.14); assert(test == ""); string test2 = "123 \t 76.14"; auto a2 = parse!(uint, string, Yes.doCount)(test2); assert(a2.data == 123 && a2.count == 3); assert(test2 == " \t 76.14");// parse bumps string test2 = tr(test2, " \t\n\r", "", "d"); // skip ws assert(test2 == "76.14"); auto b2 = parse!(double, string, Yes.doCount)(test2); assert(b2.data == 76.14 && b2.count == 5); assert(test2 == ""); } @safe unittest { import std.conv; import std.typecons : Flag, Yes, No, tuple; enum EnumType : bool { a = true, b = false, c = a } auto str = "a"; assert(parse!EnumType(str) == EnumType.a); auto str2 = "a"; assert(parse!(EnumType, string, No.doCount)(str2) == EnumType.a); auto str3 = "a"; assert(parse!(EnumType, string, Yes.doCount)(str3) == tuple(EnumType.a, 1)); } @safe unittest { import std.conv; import std.math.operations : isClose; import std.math.traits : isNaN, isInfinity; import std.typecons : Flag, Yes, No; auto str = "123.456"; assert(parse!double(str).isClose(123.456)); auto str2 = "123.456"; assert(parse!(double, string, No.doCount)(str2).isClose(123.456)); auto str3 = "123.456"; auto r = parse!(double, string, Yes.doCount)(str3); assert(r.data.isClose(123.456)); assert(r.count == 7); auto str4 = "-123.456"; r = parse!(double, string, Yes.doCount)(str4); assert(r.data.isClose(-123.456)); assert(r.count == 8); auto str5 = "+123.456"; r = parse!(double, string, Yes.doCount)(str5); assert(r.data.isClose(123.456)); assert(r.count == 8); auto str6 = "inf0"; r = parse!(double, string, Yes.doCount)(str6); assert(isInfinity(r.data) && r.count == 3 && str6 == "0"); auto str7 = "-0"; auto r2 = parse!(float, string, Yes.doCount)(str7); assert(r2.data.isClose(0.0) && r2.count == 2); auto str8 = "nan"; auto r3 = parse!(real, string, Yes.doCount)(str8); assert(isNaN(r3.data) && r3.count == 3); } @safe pure unittest { import std.conv; import std.typecons : Flag, Yes, No; auto s = "Hello, World!"; char first = parse!char(s); assert(first == 'H'); assert(s == "ello, World!"); char second = parse!(char, string, No.doCount)(s); assert(second == 'e'); assert(s == "llo, World!"); auto third = parse!(char, string, Yes.doCount)(s); assert(third.data == 'l' && third.count == 1); assert(s == "lo, World!"); } @safe pure unittest { import std.conv; import std.exception : assertThrown; import std.typecons : Flag, Yes, No; alias NullType = typeof(null); auto s1 = "null"; assert(parse!NullType(s1) is null); assert(s1 == ""); auto s2 = "NUll"d; assert(parse!NullType(s2) is null); assert(s2 == ""); auto s3 = "nuLlNULl"; assert(parse!(NullType, string, No.doCount)(s3) is null); auto r = parse!(NullType, string, Yes.doCount)(s3); assert(r.data is null && r.count == 4); auto m = "maybe"; assertThrown!ConvException(parse!NullType(m)); assertThrown!ConvException(parse!(NullType, string, Yes.doCount)(m)); assert(m == "maybe"); // m shouldn't change on failure auto s = "NULL"; assert(parse!(const NullType)(s) is null); } @safe pure unittest { import std.conv; import std.typecons : Flag, Yes, No; auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`; auto a1 = parse!(string[])(s1); assert(a1 == ["hello", "world"]); auto s2 = `["aaa", "bbb", "ccc"]`; auto a2 = parse!(string[])(s2); assert(a2 == ["aaa", "bbb", "ccc"]); auto s3 = `[['h', 'e', 'l', 'l', 'o'], "world"]`; auto len3 = s3.length; auto a3 = parse!(string[], string, Yes.doCount)(s3); assert(a3.data == ["hello", "world"]); assert(a3.count == len3); } @safe pure unittest { import std.conv; import std.typecons : Flag, Yes, No, tuple; import std.range.primitives : save; import std.array : assocArray; auto s1 = "[1:10, 2:20, 3:30]"; auto copyS1 = s1.save; auto aa1 = parse!(int[int])(s1); assert(aa1 == [1:10, 2:20, 3:30]); assert(tuple([1:10, 2:20, 3:30], copyS1.length) == parse!(int[int], string, Yes.doCount)(copyS1)); auto s2 = `["aaa":10, "bbb":20, "ccc":30]`; auto copyS2 = s2.save; auto aa2 = parse!(int[string])(s2); assert(aa2 == ["aaa":10, "bbb":20, "ccc":30]); assert(tuple(["aaa":10, "bbb":20, "ccc":30], copyS2.length) == parse!(int[string], string, Yes.doCount)(copyS2)); auto s3 = `["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]`; auto copyS3 = s3.save; auto aa3 = parse!(int[][string])(s3); assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]); assert(tuple(["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]], copyS3.length) == parse!(int[][string], string, Yes.doCount)(copyS3)); auto s4 = `[]`; int[int] emptyAA; assert(tuple(emptyAA, s4.length) == parse!(int[int], string, Yes.doCount)(s4)); } @safe unittest { import std.conv; assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c); assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w); assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d); } @safe unittest { import std.conv; // Same as 0177 auto a = octal!177; // octal is a compile-time device enum b = octal!160; // Create an unsigned octal auto c = octal!"1_000_000u"; // Leading zeros are allowed when converting from a string auto d = octal!"0001_200_000"; } @safe unittest { import std.conv; import std.traits : Unsigned; immutable int s = 42; auto u1 = unsigned(s); //not qualified static assert(is(typeof(u1) == uint)); Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification static assert(is(typeof(u2) == immutable uint)); immutable u3 = unsigned(s); //explicitly qualified } @safe unittest { import std.conv; import std.traits : Signed; immutable uint u = 42; auto s1 = signed(u); //not qualified static assert(is(typeof(s1) == int)); Signed!(typeof(u)) s2 = signed(u); //same qualification static assert(is(typeof(s2) == immutable int)); immutable s3 = signed(u); //explicitly qualified } @safe unittest { import std.conv; enum A { a = 42 } static assert(is(typeof(A.a.asOriginalType) == int)); assert(A.a.asOriginalType == 42); enum B : double { a = 43 } static assert(is(typeof(B.a.asOriginalType) == double)); assert(B.a.asOriginalType == 43); } @system unittest { import std.conv; // Regular cast, which has been verified to be legal by the programmer: { long x; auto y = cast(int) x; } // However this will still compile if 'x' is changed to be a pointer: { long* x; auto y = cast(int) x; } // castFrom provides a more reliable alternative to casting: { long x; auto y = castFrom!long.to!int(x); } // Changing the type of 'x' will now issue a compiler error, // allowing bad casts to be caught before it's too late: { long* x; static assert( !__traits(compiles, castFrom!long.to!int(x)) ); // if cast is still needed, must be changed to: auto y = castFrom!(long*).to!int(x); } } @safe unittest { import std.conv; // conversion at compile time auto string1 = hexString!"304A314B"; assert(string1 == "0J1K"); auto string2 = hexString!"304A314B"w; assert(string2 == "0J1K"w); auto string3 = hexString!"304A314B"d; assert(string3 == "0J1K"d); } @safe unittest { import std.conv; import std.algorithm.comparison : equal; assert(toChars(1).equal("1")); assert(toChars(1_000_000).equal("1000000")); assert(toChars!(2)(2U).equal("10")); assert(toChars!(16)(255U).equal("ff")); assert(toChars!(16, char, LetterCase.upper)(255U).equal("FF")); } @safe unittest { import std.conv; uint n = 0xDEADBEEF; version (LittleEndian) assert(n.bitCast!(ubyte[4]) == [0xEF, 0xBE, 0xAD, 0xDE]); version (BigEndian) assert(n.bitCast!(ubyte[4]) == [0xDE, 0xAD, 0xBE, 0xEF]); }