@@ -610,6 +610,23 @@ private template optionValidator(A...)
610610 alias optionValidator = message;
611611}
612612
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+
613630@safe pure unittest
614631{
615632 alias P = void * ;
@@ -864,7 +881,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
864881 if (val.length)
865882 {
866883 // parse '--b=true/false'
867- * receiver = to ! ( typeof ( * receiver))(val );
884+ handleConversion(option, val, receiver, i );
868885 }
869886 else
870887 {
@@ -888,15 +905,22 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
888905 val = args[i];
889906 args = args[0 .. i] ~ args[i + 1 .. $];
890907 }
891- static if (is (typeof (* receiver) == enum ))
908+ static if (is (typeof (* receiver) == enum ) ||
909+ is (typeof (* receiver) == string ))
892910 {
893- * receiver = to ! ( typeof ( * receiver))(val );
911+ handleConversion(option, val, receiver, i );
894912 }
895913 else static if (is (typeof (* receiver) : real ))
896914 {
897915 // 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+ }
900924 }
901925 else static if (is (typeof (* receiver) == string ))
902926 {
@@ -936,12 +960,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
936960
937961 if (arraySep == " " )
938962 {
939- * receiver ~= to! E(val);
963+ E tmp;
964+ handleConversion(option, val, &tmp, i);
965+ * receiver ~= tmp;
940966 }
941967 else
942968 {
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+ }
945975 }
946976 }
947977 else static if (isAssociativeArray! (typeof (* receiver)))
@@ -961,7 +991,14 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
961991 ~ to! string (assignChar) ~ " ' in argument '" ~ input ~ " '." );
962992 auto key = input[0 .. j];
963993 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);
9651002 }
9661003
9671004 static void setHash (Range )(R receiver, Range range)
@@ -1477,7 +1514,7 @@ private void setConfig(ref configuration cfg, config option) @safe pure nothrow
14771514 assertThrown! GetOptException(getopt(args, " abc" , &abc));
14781515
14791516 args = [" prog" , " --abc=string" ];
1480- assertThrown! ConvException (getopt(args, " abc" , &abc));
1517+ assertThrown! GetOptException (getopt(args, " abc" , &abc));
14811518}
14821519
14831520// https://issues.dlang.org/show_bug.cgi?id=7693
@@ -1946,3 +1983,57 @@ void defaultGetoptFormatter(Output)(Output output, string text, Option[] opt, st
19461983 ~ " information.\n " ;
19471984 assert (wanted == helpMsg);
19481985}
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