summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-11-12 11:44:45 +0100
committerEugen Wissner <belka@caraus.de>2017-11-12 11:44:45 +0100
commit4bbc8b510afdce8daebc941e46af8f986100f688 (patch)
tree689e455ee4fabc4cfcdaef1f51b7e5b91cd92ea2
parent87ea1f98dcd1a41e9376f9e7376025b911fb193b (diff)
downloadtanya-4bbc8b510afdce8daebc941e46af8f986100f688.tar.gz
conv: Use assertThrown to check ConvException is thrown
-rw-r--r--source/tanya/conv.d310
-rw-r--r--source/tanya/format/conv.d296
2 files changed, 330 insertions, 276 deletions
diff --git a/source/tanya/conv.d b/source/tanya/conv.d
index 5a5fac6..be5e0f0 100644
--- a/source/tanya/conv.d
+++ b/source/tanya/conv.d
@@ -18,6 +18,11 @@ import tanya.memory;
import tanya.memory.op;
import tanya.meta.trait;
+version (unittest)
+{
+ import tanya.test.assertion;
+}
+
/**
* Constructs a new object of type $(D_PARAM T) in $(D_PARAM memory) with the
* given arguments.
@@ -233,3 +238,308 @@ body
}
static assert(is(typeof(emplace!F((void[]).init))));
}
+
+/**
+ * Thrown if a type conversion fails.
+ */
+final class ConvException : Exception
+{
+ /**
+ * Params:
+ * msg = The message for the exception.
+ * file = The file where the exception occurred.
+ * line = The line number where the exception occurred.
+ * next = The previous exception in the chain of exceptions, if any.
+ */
+ this(string msg,
+ string file = __FILE__,
+ size_t line = __LINE__,
+ Throwable next = null) @nogc @safe pure nothrow
+ {
+ super(msg, file, line, next);
+ }
+}
+
+/**
+ * If the source type $(D_PARAM From) and the target type $(D_PARAM To) are
+ * equal, does nothing. If $(D_PARAM From) can be implicitly converted to
+ * $(D_PARAM To), just returns $(D_PARAM from).
+ *
+ * Params:
+ * To = Target type.
+ *
+ * Returns: $(D_PARAM from).
+ */
+template to(To)
+{
+ /**
+ * Params:
+ * From = Source type.
+ * from = Source value.
+ */
+ ref To to(From)(ref From from)
+ if (is(To == From))
+ {
+ return from;
+ }
+
+ /// ditto
+ To to(From)(From from)
+ if (is(Unqual!To == Unqual!From) || (isNumeric!From && isFloatingPoint!To))
+ {
+ return from;
+ }
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ auto val = 5.to!int();
+ assert(val == 5);
+ static assert(is(typeof(val) == int));
+}
+
+@nogc nothrow pure @safe unittest
+{
+ int val = 5;
+ assert(val.to!int() == 5);
+}
+
+/**
+ * Performs checked conversion from an integral type $(D_PARAM From) to an
+ * integral type $(D_PARAM To).
+ *
+ * Params:
+ * From = Source type.
+ * To = Target type.
+ * from = Source value.
+ *
+ * Returns: $(D_PARAM from) converted to $(D_PARAM To).
+ *
+ * Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is too small or too
+ * large to be represented by $(D_PARAM To).
+ */
+To to(To, From)(From from)
+if (isIntegral!From
+ && isIntegral!To
+ && !is(Unqual!To == Unqual!From)
+ && !is(To == enum))
+{
+ static if ((isUnsigned!From && isSigned!To && From.sizeof == To.sizeof)
+ || From.sizeof > To.sizeof)
+ {
+ if (from > To.max)
+ {
+ throw make!ConvException(defaultAllocator,
+ "Positive integer overflow");
+ }
+ }
+ static if (isSigned!From)
+ {
+ static if (isUnsigned!To)
+ {
+ if (from < 0)
+ {
+ throw make!ConvException(defaultAllocator,
+ "Negative integer overflow");
+ }
+ }
+ else static if (From.sizeof > To.sizeof)
+ {
+ if (from < To.min)
+ {
+ throw make!ConvException(defaultAllocator,
+ "Negative integer overflow");
+ }
+ }
+ }
+ static if (From.sizeof <= To.sizeof)
+ {
+ return from;
+ }
+ else static if (isSigned!To)
+ {
+ return cast(To) from;
+ }
+ else
+ {
+ return from & To.max;
+ }
+}
+
+@nogc nothrow pure @safe unittest
+{
+ // ubyte -> ushort
+ assert((cast(ubyte) 0).to!ushort == 0);
+ assert((cast(ubyte) 1).to!ushort == 1);
+ assert((cast(ubyte) (ubyte.max - 1)).to!ushort == ubyte.max - 1);
+ assert((cast(ubyte) ubyte.max).to!ushort == ubyte.max);
+
+ // ubyte -> short
+ assert((cast(ubyte) 0).to!short == 0);
+ assert((cast(ubyte) 1).to!short == 1);
+ assert((cast(ubyte) (ubyte.max - 1)).to!short == ubyte.max - 1);
+ assert((cast(ubyte) ubyte.max).to!short == ubyte.max);
+}
+
+@nogc pure @safe unittest
+{
+ // ubyte <- ushort
+ assert((cast(ushort) 0).to!ubyte == 0);
+ assert((cast(ushort) 1).to!ubyte == 1);
+ assert((cast(ushort) (ubyte.max - 1)).to!ubyte == ubyte.max - 1);
+ assert((cast(ushort) ubyte.max).to!ubyte == ubyte.max);
+
+ // ubyte <- short
+ assert((cast(short) 0).to!ubyte == 0);
+ assert((cast(short) 1).to!ubyte == 1);
+ assert((cast(short) (ubyte.max - 1)).to!ubyte == ubyte.max - 1);
+ assert((cast(short) ubyte.max).to!ubyte == ubyte.max);
+
+ // short <-> int
+ assert(short.min.to!int == short.min);
+ assert((short.min + 1).to!int == short.min + 1);
+ assert((cast(short) -1).to!int == -1);
+ assert((cast(short) 0).to!int == 0);
+ assert((cast(short) 1).to!int == 1);
+ assert((short.max - 1).to!int == short.max - 1);
+ assert(short.max.to!int == short.max);
+
+ assert((cast(int) short.min).to!short == short.min);
+ assert((cast(int) short.min + 1).to!short == short.min + 1);
+ assert((cast(int) -1).to!short == -1);
+ assert((cast(int) 0).to!short == 0);
+ assert((cast(int) 1).to!short == 1);
+ assert((cast(int) short.max - 1).to!short == short.max - 1);
+ assert((cast(int) short.max).to!short == short.max);
+
+ // uint <-> int
+ assert((cast(uint) 0).to!int == 0);
+ assert((cast(uint) 1).to!int == 1);
+ assert((cast(uint) (int.max - 1)).to!int == int.max - 1);
+ assert((cast(uint) int.max).to!int == int.max);
+
+ assert((cast(int) 0).to!uint == 0);
+ assert((cast(int) 1).to!uint == 1);
+ assert((cast(int) (int.max - 1)).to!uint == int.max - 1);
+ assert((cast(int) int.max).to!uint == int.max);
+}
+
+@nogc pure @safe unittest
+{
+ assertThrown!ConvException(&to!(short, int), int.min);
+ assertThrown!ConvException(&to!(short, int), int.max);
+ assertThrown!ConvException(&to!(ushort, uint), uint.max);
+ assertThrown!ConvException(&to!(uint, int), -1);
+}
+
+@nogc nothrow pure @safe unittest
+{
+ enum Test : int
+ {
+ one,
+ two,
+ }
+ assert(Test.one.to!int == 0);
+ assert(Test.two.to!int == 1);
+}
+
+/**
+ * Converts a floating point number to an integral type.
+ *
+ * Params:
+ * From = Source type.
+ * To = Target type.
+ * from = Source value.
+ *
+ * Returns: Truncated $(D_PARAM from) (everything after the decimal point is
+ * dropped).
+ *
+ * Throws: $(D_PSYMBOL ConvException) if
+ * $(D_INLINECODE from < To.min || from > To.max).
+ */
+To to(To, From)(From from)
+if (isFloatingPoint!From
+ && isIntegral!To
+ && !is(Unqual!To == Unqual!From)
+ && !is(To == enum))
+{
+ if (from > To.max)
+ {
+ throw make!ConvException(defaultAllocator,
+ "Positive number overflow");
+ }
+ else if (from < To.min)
+ {
+ throw make!ConvException(defaultAllocator,
+ "Negative number overflow");
+ }
+ return cast(To) from;
+}
+
+///
+@nogc pure @safe unittest
+{
+ assert(1.5.to!int == 1);
+ assert(2147483646.5.to!int == 2147483646);
+ assert((-2147483647.5).to!int == -2147483647);
+ assert(2147483646.5.to!uint == 2147483646);
+}
+
+@nogc pure @safe unittest
+{
+ assertThrown!ConvException(&to!(int, double), 2147483647.5);
+ assertThrown!ConvException(&to!(int, double), -2147483648.5);
+ assertThrown!ConvException(&to!(uint, double), -21474.5);
+}
+
+/**
+ * Performs checked conversion from an integral type $(D_PARAM From) to an
+ * $(D_KEYWORD enum).
+ *
+ * Params:
+ * From = Source type.
+ * To = Target type.
+ * from = Source value.
+ *
+ * Returns: $(D_KEYWORD enum) value.
+ *
+ * Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is not a member of
+ * $(D_PSYMBOL To).
+ */
+To to(To, From)(From from)
+if (isIntegral!From && is(To == enum))
+{
+ foreach (m; EnumMembers!To)
+ {
+ if (from == m)
+ {
+ return m;
+ }
+ }
+ throw make!ConvException(defaultAllocator,
+ "Value not found in enum '" ~ To.stringof ~ "'");
+}
+
+///
+@nogc pure @safe unittest
+{
+ enum Test : int
+ {
+ one,
+ two,
+ }
+ static assert(is(typeof(1.to!Test) == Test));
+ assert(0.to!Test == Test.one);
+ assert(1.to!Test == Test.two);
+}
+
+@nogc pure @safe unittest
+{
+ enum Test : uint
+ {
+ one,
+ two,
+ }
+ assertThrown!ConvException(&to!(Test, int), 5);
+}
diff --git a/source/tanya/format/conv.d b/source/tanya/format/conv.d
index 7e8841e..a86a8cd 100644
--- a/source/tanya/format/conv.d
+++ b/source/tanya/format/conv.d
@@ -20,6 +20,11 @@ import tanya.memory.op;
import tanya.meta.trait;
import tanya.meta.transform;
+version (unittest)
+{
+ import tanya.test.assertion;
+}
+
/**
* Thrown if a type conversion fails.
*/
@@ -51,6 +56,7 @@ final class ConvException : Exception
*
* Returns: $(D_PARAM from).
*/
+deprecated("Use tanya.conv.to instead")
template to(To)
{
/**
@@ -72,20 +78,6 @@ template to(To)
}
}
-///
-pure nothrow @safe @nogc unittest
-{
- auto val = 5.to!int();
- assert(val == 5);
- static assert(is(typeof(val) == int));
-}
-
-private pure nothrow @safe @nogc unittest
-{
- int val = 5;
- assert(val.to!int() == 5);
-}
-
/**
* Performs checked conversion from an integral type $(D_PARAM From) to an
* integral type $(D_PARAM To).
@@ -100,6 +92,7 @@ private pure nothrow @safe @nogc unittest
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is too small or too
* large to be represented by $(D_PARAM To).
*/
+deprecated("Use tanya.conv.to instead")
To to(To, From)(From from)
if (isIntegral!From
&& isIntegral!To
@@ -148,135 +141,6 @@ if (isIntegral!From
}
}
-private pure nothrow @safe @nogc unittest
-{
- // ubyte -> ushort
- assert((cast(ubyte) 0).to!ushort == 0);
- assert((cast(ubyte) 1).to!ushort == 1);
- assert((cast(ubyte) (ubyte.max - 1)).to!ushort == ubyte.max - 1);
- assert((cast(ubyte) ubyte.max).to!ushort == ubyte.max);
-
- // ubyte -> short
- assert((cast(ubyte) 0).to!short == 0);
- assert((cast(ubyte) 1).to!short == 1);
- assert((cast(ubyte) (ubyte.max - 1)).to!short == ubyte.max - 1);
- assert((cast(ubyte) ubyte.max).to!short == ubyte.max);
-}
-
-private unittest
-{
- // ubyte <- ushort
- assert((cast(ushort) 0).to!ubyte == 0);
- assert((cast(ushort) 1).to!ubyte == 1);
- assert((cast(ushort) (ubyte.max - 1)).to!ubyte == ubyte.max - 1);
- assert((cast(ushort) ubyte.max).to!ubyte == ubyte.max);
-
- // ubyte <- short
- assert((cast(short) 0).to!ubyte == 0);
- assert((cast(short) 1).to!ubyte == 1);
- assert((cast(short) (ubyte.max - 1)).to!ubyte == ubyte.max - 1);
- assert((cast(short) ubyte.max).to!ubyte == ubyte.max);
-
- // short <-> int
- assert(short.min.to!int == short.min);
- assert((short.min + 1).to!int == short.min + 1);
- assert((cast(short) -1).to!int == -1);
- assert((cast(short) 0).to!int == 0);
- assert((cast(short) 1).to!int == 1);
- assert((short.max - 1).to!int == short.max - 1);
- assert(short.max.to!int == short.max);
-
- assert((cast(int) short.min).to!short == short.min);
- assert((cast(int) short.min + 1).to!short == short.min + 1);
- assert((cast(int) -1).to!short == -1);
- assert((cast(int) 0).to!short == 0);
- assert((cast(int) 1).to!short == 1);
- assert((cast(int) short.max - 1).to!short == short.max - 1);
- assert((cast(int) short.max).to!short == short.max);
-
- // uint <-> int
- assert((cast(uint) 0).to!int == 0);
- assert((cast(uint) 1).to!int == 1);
- assert((cast(uint) (int.max - 1)).to!int == int.max - 1);
- assert((cast(uint) int.max).to!int == int.max);
-
- assert((cast(int) 0).to!uint == 0);
- assert((cast(int) 1).to!uint == 1);
- assert((cast(int) (int.max - 1)).to!uint == int.max - 1);
- assert((cast(int) int.max).to!uint == int.max);
-}
-
-private unittest
-{
- ConvException exception;
- try
- {
- assert(int.min.to!short == int.min);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private unittest
-{
- ConvException exception;
- try
- {
- assert(int.max.to!short == int.max);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private unittest
-{
- ConvException exception;
- try
- {
- assert(uint.max.to!ushort == ushort.max);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private unittest
-{
- ConvException exception;
- try
- {
- assert((-1).to!uint == -1);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private @nogc unittest
-{
- enum Test : int
- {
- one,
- two,
- }
- assert(Test.one.to!int == 0);
- assert(Test.two.to!int == 1);
-}
-
/**
* Converts $(D_PARAM from) to a boolean.
*
@@ -317,7 +181,7 @@ if (isNumeric!From && is(Unqual!To == bool) && !is(Unqual!To == Unqual!From))
}
///
-@nogc unittest
+@nogc pure @safe unittest
{
assert(!0.0.to!bool);
assert(0.2.to!bool);
@@ -328,34 +192,10 @@ if (isNumeric!From && is(Unqual!To == bool) && !is(Unqual!To == Unqual!From))
assert(1.to!bool);
}
-private @nogc unittest
+@nogc pure @safe unittest
{
- ConvException exception;
- try
- {
- assert((-1).to!bool);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private @nogc unittest
-{
- ConvException exception;
- try
- {
- assert(2.to!bool);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
+ assertThrown!ConvException(&to!(bool, int), -1);
+ assertThrown!ConvException(&to!(bool, int), 2);
}
/// ditto
@@ -375,7 +215,7 @@ if ((is(From == String) || isSomeString!From) && is(Unqual!To == bool))
}
///
-@nogc unittest
+@nogc pure @safe unittest
{
assert("true".to!bool);
assert(!"false".to!bool);
@@ -384,19 +224,9 @@ if ((is(From == String) || isSomeString!From) && is(Unqual!To == bool))
}
-private @nogc unittest
+@nogc pure @safe unittest
{
- ConvException exception;
- try
- {
- assert("1".to!bool);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
+ assertThrown!ConvException(() => "1".to!bool);
}
/**
@@ -422,7 +252,7 @@ if (is(Unqual!From == bool) && isNumeric!To && !is(Unqual!To == Unqual!From))
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(true.to!float == 1.0);
assert(true.to!double == 1.0);
@@ -451,13 +281,13 @@ if (is(Unqual!From == bool) && is(Unqual!To == String))
}
///
-@nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(true.to!String == "true");
assert(false.to!String == "false");
}
-private @nogc unittest
+@nogc nothrow pure @safe unittest
{
static assert(is(typeof((const String("true")).to!bool)));
static assert(is(typeof(false.to!(const String) == "false")));
@@ -477,6 +307,7 @@ private @nogc unittest
* Throws: $(D_PSYMBOL ConvException) if
* $(D_INLINECODE from < To.min || from > To.max).
*/
+deprecated("Use tanya.conv.to instead")
To to(To, From)(From from)
if (isFloatingPoint!From
&& isIntegral!To
@@ -496,60 +327,6 @@ if (isFloatingPoint!From
return cast(To) from;
}
-///
-@nogc unittest
-{
- assert(1.5.to!int == 1);
- assert(2147483646.5.to!int == 2147483646);
- assert((-2147483647.5).to!int == -2147483647);
- assert(2147483646.5.to!uint == 2147483646);
-}
-
-private @nogc unittest
-{
- ConvException exception;
- try
- {
- assert(2147483647.5.to!int == 2147483647);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private @nogc unittest
-{
- ConvException exception;
- try
- {
- assert((-2147483648.5).to!int == -2147483648);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
-private @nogc unittest
-{
- ConvException exception;
- try
- {
- assert((-21474.5).to!uint == -21474);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
/**
* Performs checked conversion from an integral type $(D_PARAM From) to an
* $(D_KEYWORD enum).
@@ -564,6 +341,7 @@ private @nogc unittest
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is not a member of
* $(D_PSYMBOL To).
*/
+deprecated("Use tanya.conv.to instead")
To to(To, From)(From from)
if (isIntegral!From && is(To == enum))
{
@@ -578,40 +356,6 @@ if (isIntegral!From && is(To == enum))
"Value not found in enum '" ~ To.stringof ~ "'");
}
-///
-@nogc unittest
-{
- enum Test : int
- {
- one,
- two,
- }
- static assert(is(typeof(1.to!Test) == Test));
- assert(0.to!Test == Test.one);
- assert(1.to!Test == Test.two);
-}
-
-private @nogc unittest
-{
- enum Test : uint
- {
- one,
- two,
- }
-
- ConvException exception;
- try
- {
- assert(5.to!Test == Test.one);
- }
- catch (ConvException e)
- {
- exception = e;
- }
- assert(exception !is null);
- defaultAllocator.dispose(exception);
-}
-
// Returns the last part of buffer with converted number.
package(tanya) char[] number2String(T)(const T number,
return ref char[21] buffer)
@@ -679,7 +423,7 @@ if (isIntegral!T)
}
// Converting an integer to string.
-private pure nothrow @system @nogc unittest
+@nogc nothrow pure @system unittest
{
char[21] buf;