Skip to content

Commit ffd50b9

Browse files
committedFeb 22, 2012
Make the various from_str functions return options
So that they can be used with user input without causing task failures. Closes #1335
1 parent 7237343 commit ffd50b9

26 files changed

+203
-315
lines changed
 

‎src/comp/metadata/decoder.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,8 @@ fn variant_enum_id(d: ebml::doc) -> ast::def_id {
9595
}
9696

9797
fn variant_disr_val(d: ebml::doc) -> option<int> {
98-
alt ebml::maybe_get_doc(d, tag_disr_val) {
99-
some(val_doc) {
100-
let val_buf = ebml::doc_data(val_doc);
101-
let val = int::parse_buf(val_buf, 10u);
102-
ret some(val);
103-
}
104-
_ { ret none;}
98+
option::chain(ebml::maybe_get_doc(d, tag_disr_val)) {|val_doc|
99+
int::parse_buf(ebml::doc_data(val_doc), 10u)
105100
}
106101
}
107102

‎src/comp/metadata/tydecode.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,8 @@ fn parse_def_id(buf: [u8]) -> ast::def_id {
390390
for b: u8 in crate_part { crate_part_vec += [b]; }
391391
for b: u8 in def_part { def_part_vec += [b]; }
392392

393-
let crate_num = uint::parse_buf(crate_part_vec, 10u) as int;
394-
let def_num = uint::parse_buf(def_part_vec, 10u) as int;
393+
let crate_num = option::get(uint::parse_buf(crate_part_vec, 10u)) as int;
394+
let def_num = option::get(uint::parse_buf(def_part_vec, 10u)) as int;
395395
ret {crate: crate_num, node: def_num};
396396
}
397397

‎src/comp/syntax/ast_util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ fn lit_to_const(lit: @lit) -> const_val {
301301
lit_str(s) { const_str(s) }
302302
lit_int(n, _) { const_int(n) }
303303
lit_uint(n, _) { const_uint(n) }
304-
lit_float(n, _) { const_float(float::from_str(n)) }
304+
lit_float(n, _) { const_float(option::get(float::from_str(n))) }
305305
lit_nil { const_int(0i64) }
306306
lit_bool(b) { const_int(b as i64) }
307307
}

‎src/comp/syntax/parse/lexer.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ fn scan_digits(rdr: reader, radix: uint) -> str {
174174
while true {
175175
let c = rdr.curr;
176176
if c == '_' { rdr.bump(); cont; }
177-
alt char::maybe_digit(c) {
178-
some(d) if (d as uint) < radix {
177+
alt char::to_digit(c, radix) {
178+
some(d) {
179179
str::push_char(rslt, c);
180180
rdr.bump();
181181
}
@@ -229,7 +229,7 @@ fn scan_number(c: char, rdr: reader) -> token::token {
229229
if str::len_bytes(num_str) == 0u {
230230
rdr.fatal("no valid digits found for number");
231231
}
232-
let parsed = u64::from_str(num_str, base as u64);
232+
let parsed = option::get(u64::from_str(num_str, base as u64));
233233
alt tp {
234234
either::left(t) { ret token::LIT_INT(parsed as i64, t); }
235235
either::right(t) { ret token::LIT_UINT(parsed, t); }
@@ -276,7 +276,7 @@ fn scan_number(c: char, rdr: reader) -> token::token {
276276
if str::len_bytes(num_str) == 0u {
277277
rdr.fatal("no valid digits found for number");
278278
}
279-
let parsed = u64::from_str(num_str, base as u64);
279+
let parsed = option::get(u64::from_str(num_str, base as u64));
280280
ret token::LIT_INT(parsed as i64, ast::ty_i);
281281
}
282282
}

‎src/libcore/bool.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ pure fn is_false(v: t) -> bool { !v }
5959
#[doc(
6060
brief = "Parse logic value from `s`"
6161
)]
62-
pure fn from_str(s: str) -> t {
62+
pure fn from_str(s: str) -> option<t> {
6363
alt check s {
64-
"true" { true }
65-
"false" { false }
66-
_ { fail "'" + s + "' is not a valid boolean string"; }
64+
"true" { some(true) }
65+
"false" { some(false) }
66+
_ { none }
6767
}
6868
}
6969

@@ -89,7 +89,7 @@ pure fn to_bit(v: t) -> u8 { if v { 1u8 } else { 0u8 } }
8989
#[test]
9090
fn test_bool_from_str() {
9191
all_values { |v|
92-
assert v == from_str(bool::to_str(v))
92+
assert some(v) == from_str(bool::to_str(v))
9393
}
9494
}
9595

‎src/libcore/char.rs

+25-44
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export is_alphabetic,
3838
is_lowercase, is_uppercase,
3939
is_whitespace, is_alphanumeric,
4040
is_ascii, is_digit,
41-
to_digit, to_lower, to_upper, maybe_digit, cmp;
41+
to_digit, to_lower, to_upper, cmp;
4242

4343
import is_alphabetic = unicode::derived_property::Alphabetic;
4444
import is_XID_start = unicode::derived_property::XID_Start;
@@ -102,26 +102,18 @@ pure fn is_digit(c: char) -> bool {
102102
Safety note: This function fails if `c` is not a valid char",
103103
return = "If `c` is between '0' and '9', the corresponding value \
104104
between 0 and 9. If `c` is 'a' or 'A', 10. If `c` is \
105-
'b' or 'B', 11, etc."
105+
'b' or 'B', 11, etc. Returns none if the char does not \
106+
refer to a digit in the given radix."
106107
)]
107-
pure fn to_digit(c: char) -> u8 unsafe {
108-
alt maybe_digit(c) {
109-
option::some(x) { x }
110-
option::none { fail; }
111-
}
112-
}
113-
114-
#[doc(
115-
brief = "Convert a char to the corresponding digit. Returns none when \
116-
character is not a valid hexadecimal digit."
117-
)]
118-
pure fn maybe_digit(c: char) -> option<u8> {
119-
alt c {
120-
'0' to '9' { option::some(c as u8 - ('0' as u8)) }
121-
'a' to 'z' { option::some(c as u8 + 10u8 - ('a' as u8)) }
122-
'A' to 'Z' { option::some(c as u8 + 10u8 - ('A' as u8)) }
123-
_ { option::none }
124-
}
108+
pure fn to_digit(c: char, radix: uint) -> option<uint> {
109+
let val = alt c {
110+
'0' to '9' { c as uint - ('0' as uint) }
111+
'a' to 'z' { c as uint + 10u - ('a' as uint) }
112+
'A' to 'Z' { c as uint + 10u - ('A' as uint) }
113+
_ { ret none; }
114+
};
115+
if val < radix { some(val) }
116+
else { none }
125117
}
126118

127119
/*
@@ -192,30 +184,19 @@ fn test_is_whitespace() {
192184

193185
#[test]
194186
fn test_to_digit() {
195-
assert (to_digit('0') == 0u8);
196-
assert (to_digit('1') == 1u8);
197-
assert (to_digit('2') == 2u8);
198-
assert (to_digit('9') == 9u8);
199-
assert (to_digit('a') == 10u8);
200-
assert (to_digit('A') == 10u8);
201-
assert (to_digit('b') == 11u8);
202-
assert (to_digit('B') == 11u8);
203-
assert (to_digit('z') == 35u8);
204-
assert (to_digit('Z') == 35u8);
205-
}
206-
207-
#[test]
208-
#[should_fail]
209-
#[ignore(cfg(target_os = "win32"))]
210-
fn test_to_digit_fail_1() {
211-
to_digit(' ');
212-
}
213-
214-
#[test]
215-
#[should_fail]
216-
#[ignore(cfg(target_os = "win32"))]
217-
fn test_to_digit_fail_2() {
218-
to_digit('$');
187+
assert to_digit('0', 10u) == some(0u);
188+
assert to_digit('1', 2u) == some(1u);
189+
assert to_digit('2', 3u) == some(2u);
190+
assert to_digit('9', 10u) == some(9u);
191+
assert to_digit('a', 16u) == some(10u);
192+
assert to_digit('A', 16u) == some(10u);
193+
assert to_digit('b', 16u) == some(11u);
194+
assert to_digit('B', 16u) == some(11u);
195+
assert to_digit('z', 36u) == some(35u);
196+
assert to_digit('Z', 36u) == some(35u);
197+
198+
assert to_digit(' ', 10u) == none;
199+
assert to_digit('$', 36u) == none;
219200
}
220201

221202
#[test]

‎src/libcore/float.rs

+42-46
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,27 @@ Leading and trailing whitespace are ignored.
122122
123123
Parameters:
124124
125-
num - A string, possibly empty.
125+
num - A string
126126
127127
Returns:
128128
129-
<NaN> If the string did not represent a valid number.
130-
Otherwise, the floating-point number represented [num].
129+
none if the string did not represent a valid number.
130+
Otherwise, some(n) where n is the floating-point
131+
number represented by [num].
131132
*/
132-
fn from_str(num: str) -> float {
133-
let num = str::trim(num);
134-
133+
fn from_str(num: str) -> option<float> {
135134
let pos = 0u; //Current byte position in the string.
136135
//Used to walk the string in O(n).
137136
let len = str::len_bytes(num); //Length of the string, in bytes.
138137

139-
if len == 0u { ret 0.; }
138+
if len == 0u { ret none; }
140139
let total = 0f; //Accumulated result
141140
let c = 'z'; //Latest char.
142141

143142
//The string must start with one of the following characters.
144143
alt str::char_at(num, 0u) {
145144
'-' | '+' | '0' to '9' | '.' {}
146-
_ { ret NaN; }
145+
_ { ret none; }
147146
}
148147

149148
//Determine if first char is '-'/'+'. Set [pos] and [neg] accordingly.
@@ -173,7 +172,7 @@ fn from_str(num: str) -> float {
173172
break;
174173
}
175174
_ {
176-
ret NaN;
175+
ret none;
177176
}
178177
}
179178
}
@@ -193,7 +192,7 @@ fn from_str(num: str) -> float {
193192
break;
194193
}
195194
_ {
196-
ret NaN;
195+
ret none;
197196
}
198197
}
199198
}
@@ -238,17 +237,17 @@ fn from_str(num: str) -> float {
238237
total = total * multiplier;
239238
}
240239
} else {
241-
ret NaN;
240+
ret none;
242241
}
243242
}
244243

245244
if(pos < len) {
246-
ret NaN;
245+
ret none;
247246
} else {
248247
if(neg) {
249248
total *= -1f;
250249
}
251-
ret total;
250+
ret some(total);
252251
}
253252
}
254253

@@ -291,39 +290,36 @@ fn pow_uint_to_uint_as_float(x: uint, pow: uint) -> float {
291290

292291
#[test]
293292
fn test_from_str() {
294-
assert ( from_str("3") == 3. );
295-
assert ( from_str(" 3 ") == 3. );
296-
assert ( from_str("3.14") == 3.14 );
297-
assert ( from_str("+3.14") == 3.14 );
298-
assert ( from_str("-3.14") == -3.14 );
299-
assert ( from_str("2.5E10") == 25000000000. );
300-
assert ( from_str("2.5e10") == 25000000000. );
301-
assert ( from_str("25000000000.E-10") == 2.5 );
302-
assert ( from_str("") == 0. );
303-
assert ( from_str(".") == 0. );
304-
assert ( from_str(".e1") == 0. );
305-
assert ( from_str(".e-1") == 0. );
306-
assert ( from_str("5.") == 5. );
307-
assert ( from_str(".5") == 0.5 );
308-
assert ( from_str("0.5") == 0.5 );
309-
assert ( from_str("0.5 ") == 0.5 );
310-
assert ( from_str(" 0.5 ") == 0.5 );
311-
assert ( from_str(" -.5 ") == -0.5 );
312-
assert ( from_str(" -.5 ") == -0.5 );
313-
assert ( from_str(" -5 ") == -5. );
314-
315-
assert ( is_NaN(from_str("x")) );
316-
assert ( from_str(" ") == 0. );
317-
assert ( from_str(" ") == 0. );
318-
assert ( from_str(" 0.5") == 0.5 );
319-
assert ( from_str(" 0.5 ") == 0.5 );
320-
assert ( from_str(" .1 ") == 0.1 );
321-
assert ( is_NaN(from_str("e")) );
322-
assert ( is_NaN(from_str("E")) );
323-
assert ( is_NaN(from_str("E1")) );
324-
assert ( is_NaN(from_str("1e1e1")) );
325-
assert ( is_NaN(from_str("1e1.1")) );
326-
assert ( is_NaN(from_str("1e1-1")) );
293+
assert from_str("3") == some(3.);
294+
assert from_str("3") == some(3.);
295+
assert from_str("3.14") == some(3.14);
296+
assert from_str("+3.14") == some(3.14);
297+
assert from_str("-3.14") == some(-3.14);
298+
assert from_str("2.5E10") == some(25000000000.);
299+
assert from_str("2.5e10") == some(25000000000.);
300+
assert from_str("25000000000.E-10") == some(2.5);
301+
assert from_str(".") == some(0.);
302+
assert from_str(".e1") == some(0.);
303+
assert from_str(".e-1") == some(0.);
304+
assert from_str("5.") == some(5.);
305+
assert from_str(".5") == some(0.5);
306+
assert from_str("0.5") == some(0.5);
307+
assert from_str("0.5") == some(0.5);
308+
assert from_str("0.5") == some(0.5);
309+
assert from_str("-.5") == some(-0.5);
310+
assert from_str("-.5") == some(-0.5);
311+
assert from_str("-5") == some(-5.);
312+
313+
assert from_str("") == none;
314+
assert from_str("x") == none;
315+
assert from_str(" ") == none;
316+
assert from_str(" ") == none;
317+
assert from_str("e") == none;
318+
assert from_str("E") == none;
319+
assert from_str("E1") == none;
320+
assert from_str("1e1e1") == none;
321+
assert from_str("1e1.1") == none;
322+
assert from_str("1e1-1") == none;
327323
}
328324

329325
#[test]

0 commit comments

Comments
 (0)