| @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]); |
| } |
| |