| @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; | |
| import std.array : appender; | |
| auto output = appender!string(); | |
| output.writeText("The answer is ", 42); | |
| assert(output.data == "The answer is 42"); | |
| } | |
| @safe unittest | |
| { | |
| import std.conv; | |
| import std.array : appender; | |
| const color = "red"; | |
| auto output = appender!string(); | |
| output.writeText(i"My favorite color is $(color)"); | |
| assert(output.data == "My favorite color is red"); | |
| } | |
| @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]); | |
| } | |