Merge pull request #1725 from youknowone/fix-parse-number

parse_number can raise error about length
This commit is contained in:
Jeong YunWon
2020-02-03 11:12:11 +09:00
committed by GitHub
2 changed files with 17 additions and 14 deletions

View File

@@ -563,7 +563,8 @@ class TypesTests(unittest.TestCase):
test(12345.6, "1=20", '111111111111112345.6')
test(12345.6, "*=20", '*************12345.6')
@unittest.skip("TODO: RUSTPYTHON")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_format_spec_errors(self):
# int, float, and string all share the same format spec
# mini-language parser.

View File

@@ -155,16 +155,17 @@ fn parse_fill_and_align(text: &str) -> (Option<char>, Option<FormatAlign>, &str)
}
}
fn parse_number(text: &str) -> (Option<usize>, &str) {
fn parse_number(text: &str) -> Result<(Option<usize>, &str), &'static str> {
let num_digits: usize = get_num_digits(text);
if num_digits == 0 {
return (None, text);
return Ok((None, text));
}
if let Ok(num) = text[..num_digits].parse::<usize>() {
Ok((Some(num), &text[num_digits..]))
} else {
// NOTE: this condition is different from CPython
Err("Too many decimal digits in format string")
}
// This should never fail
(
Some(text[..num_digits].parse::<usize>().unwrap()),
&text[num_digits..],
)
}
fn parse_sign(text: &str) -> (Option<FormatSign>, &str) {
@@ -193,11 +194,11 @@ fn parse_zero(text: &str) -> (bool, &str) {
}
}
fn parse_precision(text: &str) -> (Option<usize>, &str) {
fn parse_precision(text: &str) -> Result<(Option<usize>, &str), &'static str> {
let mut chars = text.chars();
match chars.next() {
Ok(match chars.next() {
Some('.') => {
let (size, remaining) = parse_number(&chars.as_str());
let (size, remaining) = parse_number(&chars.as_str())?;
if size.is_some() {
(size, remaining)
} else {
@@ -205,7 +206,7 @@ fn parse_precision(text: &str) -> (Option<usize>, &str) {
}
}
_ => (None, text),
}
})
}
fn parse_grouping_option(text: &str) -> (Option<FormatGrouping>, &str) {
@@ -239,14 +240,15 @@ fn parse_format_type(text: &str) -> (Option<FormatType>, &str) {
}
fn parse_format_spec(text: &str) -> Result<FormatSpec, &'static str> {
// get_integer in CPython
let (preconversor, after_preconversor) = parse_preconversor(text);
let (mut fill, mut align, after_align) = parse_fill_and_align(after_preconversor);
let (sign, after_sign) = parse_sign(after_align);
let (alternate_form, after_alternate_form) = parse_alternate_form(after_sign);
let (zero, after_zero) = parse_zero(after_alternate_form);
let (width, after_width) = parse_number(after_zero);
let (width, after_width) = parse_number(after_zero)?;
let (grouping_option, after_grouping_option) = parse_grouping_option(after_width);
let (precision, after_precision) = parse_precision(after_grouping_option);
let (precision, after_precision) = parse_precision(after_grouping_option)?;
let (format_type, after_format_type) = parse_format_type(after_precision);
if !after_format_type.is_empty() {
return Err("Invalid format specifier");