Add support for enums to format.conv.to. Fix #240
This commit is contained in:
parent
a4de1cc754
commit
e5f83c22fa
@ -38,7 +38,8 @@ final class ConvException : Exception
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If the source type $(D_PARAM From) and the target type $(D_PARAM To) are
|
* If the source type $(D_PARAM From) and the target type $(D_PARAM To) are
|
||||||
* equal, does nothing.
|
* equal, does nothing. If $(D_PARAM From) can be implicitly converted to
|
||||||
|
* $(D_PARAM To), just returns $(D_PARAM from).
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* From = Source type.
|
* From = Source type.
|
||||||
@ -56,7 +57,7 @@ template to(To)
|
|||||||
}
|
}
|
||||||
|
|
||||||
To to(From)(From from)
|
To to(From)(From from)
|
||||||
if (is(Unqual!To == Unqual!From))
|
if (is(Unqual!To == Unqual!From) || isNumeric!From && isFloatingPoint!To)
|
||||||
{
|
{
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
@ -78,9 +79,7 @@ private pure nothrow @safe @nogc unittest
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs checked conversion from an integral type $(D_PARAM From) to an
|
* Performs checked conversion from an integral type $(D_PARAM From) to an
|
||||||
* integral type $(D_PARAM To). If the conversion isn't possible (for example
|
* integral type $(D_PARAM To).
|
||||||
* because $(D_PARAM from) is too small or too large to be represented by
|
|
||||||
* $(D_PARAM To)), an exception is thrown.
|
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* From = Source type.
|
* From = Source type.
|
||||||
@ -89,10 +88,14 @@ private pure nothrow @safe @nogc unittest
|
|||||||
*
|
*
|
||||||
* Returns: $(D_PARAM from) converted to $(D_PARAM To).
|
* Returns: $(D_PARAM from) converted to $(D_PARAM To).
|
||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL ConvException).
|
* 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)
|
To to(To, From)(From from)
|
||||||
if (isIntegral!From && isIntegral!To && !is(To == From))
|
if (isIntegral!From
|
||||||
|
&& isIntegral!To
|
||||||
|
&& !is(Unqual!To == Unqual!From)
|
||||||
|
&& !is(To == enum))
|
||||||
{
|
{
|
||||||
static if ((isUnsigned!From && isSigned!To && From.sizeof == To.sizeof)
|
static if ((isUnsigned!From && isSigned!To && From.sizeof == To.sizeof)
|
||||||
|| From.sizeof > To.sizeof)
|
|| From.sizeof > To.sizeof)
|
||||||
@ -254,10 +257,19 @@ private unittest
|
|||||||
defaultAllocator.dispose(exception);
|
defaultAllocator.dispose(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @nogc unittest
|
||||||
|
{
|
||||||
|
enum Test : int
|
||||||
|
{
|
||||||
|
one,
|
||||||
|
two,
|
||||||
|
}
|
||||||
|
assert(Test.one.to!int == 0);
|
||||||
|
assert(Test.two.to!int == 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a number to a boolean. If $(D_PARAM from) is greater than `1` or
|
* Converts a number to a boolean.
|
||||||
* less than `0`, an exception is thrown, `0` results in $(D_KEYWORD false) and
|
|
||||||
* all other values result in $(D_KEYWORD true).
|
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* From = Source type.
|
* From = Source type.
|
||||||
@ -267,10 +279,11 @@ private unittest
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE from > 0 && from <= 1),
|
* Returns: $(D_KEYWORD true) if $(D_INLINECODE from > 0 && from <= 1),
|
||||||
* otherwise $(D_KEYWORD false).
|
* otherwise $(D_KEYWORD false).
|
||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL ConvException).
|
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is greater than `1` or
|
||||||
|
* less than `0`.
|
||||||
*/
|
*/
|
||||||
To to(To, From)(From from)
|
To to(To, From)(From from)
|
||||||
if (isNumeric!From && is(Unqual!To == bool) && !is(To == From))
|
if (isNumeric!From && is(Unqual!To == bool) && !is(Unqual!To == Unqual!From))
|
||||||
{
|
{
|
||||||
if (from == 0)
|
if (from == 0)
|
||||||
{
|
{
|
||||||
@ -289,7 +302,7 @@ if (isNumeric!From && is(Unqual!To == bool) && !is(To == From))
|
|||||||
"Positive number overflow");
|
"Positive number overflow");
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
private @nogc unittest
|
||||||
{
|
{
|
||||||
assert(0.0.to!bool == false);
|
assert(0.0.to!bool == false);
|
||||||
assert(0.2.to!bool == true);
|
assert(0.2.to!bool == true);
|
||||||
@ -300,7 +313,7 @@ private unittest
|
|||||||
assert(1.to!bool == true);
|
assert(1.to!bool == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
private @nogc unittest
|
||||||
{
|
{
|
||||||
ConvException exception;
|
ConvException exception;
|
||||||
try
|
try
|
||||||
@ -315,7 +328,7 @@ private unittest
|
|||||||
defaultAllocator.dispose(exception);
|
defaultAllocator.dispose(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unittest
|
private @nogc unittest
|
||||||
{
|
{
|
||||||
ConvException exception;
|
ConvException exception;
|
||||||
try
|
try
|
||||||
@ -342,7 +355,7 @@ private unittest
|
|||||||
* Returns: `1` if $(D_PARAM from) is $(D_KEYWORD true), otherwise `0`.
|
* Returns: `1` if $(D_PARAM from) is $(D_KEYWORD true), otherwise `0`.
|
||||||
*/
|
*/
|
||||||
To to(To, From)(From from)
|
To to(To, From)(From from)
|
||||||
if (is(Unqual!From == bool) && isNumeric!To && !is(To == From))
|
if (is(Unqual!From == bool) && isNumeric!To && !is(Unqual!To == Unqual!From))
|
||||||
{
|
{
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
@ -368,3 +381,153 @@ pure nothrow @safe @nogc unittest
|
|||||||
assert(false.to!uint == 0);
|
assert(false.to!uint == 0);
|
||||||
assert(false.to!int == 0);
|
assert(false.to!int == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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).
|
||||||
|
*
|
||||||
|
* 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 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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user