@@ -610,6 +610,23 @@ private template optionValidator(A...)
610
610
alias optionValidator = message;
611
611
}
612
612
613
+ private void handleConversion (R)(string option, string value, R* receiver,
614
+ size_t idx, string file = __FILE__ , size_t line = __LINE__ )
615
+ {
616
+ import std.conv : to, ConvException;
617
+ import std.format : format;
618
+ try
619
+ {
620
+ * receiver = to! (typeof (* receiver))(value);
621
+ }
622
+ catch (ConvException e)
623
+ {
624
+ throw new GetOptException(format(" Argument '%s' at position '%u' could "
625
+ ~ " not be converted to type '%s' as required by option '%s'." ,
626
+ value, idx, R.stringof, option), e, file, line);
627
+ }
628
+ }
629
+
613
630
@safe pure unittest
614
631
{
615
632
alias P = void * ;
@@ -864,7 +881,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
864
881
if (val.length)
865
882
{
866
883
// parse '--b=true/false'
867
- * receiver = to ! ( typeof ( * receiver))(val );
884
+ handleConversion(option, val, receiver, i );
868
885
}
869
886
else
870
887
{
@@ -888,15 +905,22 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
888
905
val = args[i];
889
906
args = args[0 .. i] ~ args[i + 1 .. $];
890
907
}
891
- static if (is (typeof (* receiver) == enum ))
908
+ static if (is (typeof (* receiver) == enum ) ||
909
+ is (typeof (* receiver) == string ))
892
910
{
893
- * receiver = to ! ( typeof ( * receiver))(val );
911
+ handleConversion(option, val, receiver, i );
894
912
}
895
913
else static if (is (typeof (* receiver) : real ))
896
914
{
897
915
// numeric receiver
898
- if (incremental) ++ * receiver;
899
- else * receiver = to! (typeof (* receiver))(val);
916
+ if (incremental)
917
+ {
918
+ ++ * receiver;
919
+ }
920
+ else
921
+ {
922
+ handleConversion(option, val, receiver, i);
923
+ }
900
924
}
901
925
else static if (is (typeof (* receiver) == string ))
902
926
{
@@ -936,12 +960,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
936
960
937
961
if (arraySep == " " )
938
962
{
939
- * receiver ~= to! E(val);
963
+ E tmp;
964
+ handleConversion(option, val, &tmp, i);
965
+ * receiver ~= tmp;
940
966
}
941
967
else
942
968
{
943
- foreach (elem; val.splitter(arraySep).map! (a => to! E(a))())
944
- * receiver ~= elem;
969
+ foreach (elem; val.splitter(arraySep))
970
+ {
971
+ E tmp;
972
+ handleConversion(option, elem, &tmp, i);
973
+ * receiver ~= tmp;
974
+ }
945
975
}
946
976
}
947
977
else static if (isAssociativeArray! (typeof (* receiver)))
@@ -961,7 +991,14 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
961
991
~ to! string (assignChar) ~ " ' in argument '" ~ input ~ " '." );
962
992
auto key = input[0 .. j];
963
993
auto value = input[j + 1 .. $];
964
- return tuple (to! K(key), to! V(value));
994
+
995
+ K k;
996
+ handleConversion(" " , key, &k, 0 );
997
+
998
+ V v;
999
+ handleConversion(" " , value, &v, 0 );
1000
+
1001
+ return tuple (k,v);
965
1002
}
966
1003
967
1004
static void setHash (Range )(R receiver, Range range)
@@ -1477,7 +1514,7 @@ private void setConfig(ref configuration cfg, config option) @safe pure nothrow
1477
1514
assertThrown! GetOptException(getopt(args, " abc" , &abc));
1478
1515
1479
1516
args = [" prog" , " --abc=string" ];
1480
- assertThrown! ConvException (getopt(args, " abc" , &abc));
1517
+ assertThrown! GetOptException (getopt(args, " abc" , &abc));
1481
1518
}
1482
1519
1483
1520
// https://issues.dlang.org/show_bug.cgi?id=7693
@@ -1946,3 +1983,57 @@ void defaultGetoptFormatter(Output)(Output output, string text, Option[] opt, st
1946
1983
~ " information.\n " ;
1947
1984
assert (wanted == helpMsg);
1948
1985
}
1986
+
1987
+
1988
+ @safe unittest
1989
+ {
1990
+ import std.string : indexOf;
1991
+
1992
+ enum UniqueIdentifer {
1993
+ a,
1994
+ b
1995
+ }
1996
+
1997
+ UniqueIdentifer a;
1998
+
1999
+ auto args = [" prog" , " --foo" , " HELLO" ];
2000
+ try
2001
+ {
2002
+ auto t = getopt(args, " foo|f" , &a);
2003
+ assert (false , " Must not be reached, as \" HELLO\" cannot be converted"
2004
+ ~ " to enum A." );
2005
+ }
2006
+ catch (GetOptException e)
2007
+ {
2008
+ string str = () @trusted { return e.toString(); }();
2009
+ assert (str.indexOf(" HELLO" ) != - 1 );
2010
+ assert (str.indexOf(" UniqueIdentifer" ) != - 1 );
2011
+ assert (str.indexOf(" foo" ) != - 1 );
2012
+ }
2013
+ }
2014
+
2015
+ @safe unittest
2016
+ {
2017
+ import std.string : indexOf;
2018
+
2019
+ int a;
2020
+
2021
+ auto args = [" prog" , " --foo" , " HELLO" ];
2022
+ try
2023
+ {
2024
+ auto t = getopt(args, " foo|f" , &a);
2025
+ assert (false , " Must not be reached, as \" HELLO\" cannot be converted"
2026
+ ~ " to an int" );
2027
+ }
2028
+ catch (GetOptException e)
2029
+ {
2030
+ string str = () @trusted { return e.toString(); }();
2031
+ assert (str.indexOf(" HELLO" ) != - 1 );
2032
+ assert (str.indexOf(" int" ) != - 1 );
2033
+ assert (str.indexOf(" foo" ) != - 1 );
2034
+ }
2035
+
2036
+ args = [" prog" , " --foo" , " 1337" ];
2037
+ getopt(args, " foo|f" , &a);
2038
+ assert (a == 1337 );
2039
+ }
0 commit comments