_ => (None, input),
}
}
-
+ fn strip_integer(mut input: &str, grouping: Option<char>) -> &str {
+ while let Some(rest) = input.strip_prefix(|c: char| c.is_ascii_digit()) {
+ let rest = if let Some(grouping) = grouping {
+ rest.strip_prefix(grouping).unwrap_or(rest)
+ } else {
+ rest
+ };
+ input = rest;
+ }
+ input
+ }
fn take<'a>(input: &'a str, rest: &'a str) -> (&'a str, &'a str) {
(&input[..input.len() - rest.len()], rest)
}
- let (saw_prefix, input) = strip_prefix(input, &*style.prefix.s);
+ let (_, input) = strip_prefix(input, &*style.prefix.s);
let (sign, input) = strip_one_of(input, &['-', '+']);
- let input = if sign.is_some() && !saw_prefix {
+ let input = if sign.is_some() {
strip_prefix(input, &*style.prefix.s).1
} else {
input
};
- let (integer, input) = take(
- input,
- input.trim_start_matches(|c: char| c.is_ascii_digit()),
- );
- let (decimals, input) = if let Some(rest) = input.strip_prefix('.') {
+ let (integer, input) = take(input, strip_integer(input, style.grouping.map(char::from)));
+ let (decimals, input) = if let Some(rest) = input.strip_prefix(style.decimal.as_str()) {
take(rest, rest.trim_start_matches(|c: char| c.is_ascii_digit()))
} else {
("", input)
if let Some(sign) = sign {
number.push(sign);
}
- number.push_str(integer);
+ number.extend(integer.chars().filter(|c| c.is_ascii_digit()));
if !decimals.is_empty() {
write!(&mut number, ".{decimals}").unwrap();
}
use crate::{
dictionary::Value,
format::{Format, Type},
+ settings::Settings,
};
- #[test]
- fn number() {
+ fn test(name: &str, type_: Type) {
let base = Path::new(env!("CARGO_MANIFEST_DIR")).join("src/format/testdata/parse");
let input_stream = BufReader::new(File::open(base.join("num-in.txt")).unwrap());
- let expected_stream = BufReader::new(File::open(base.join("num-in.expected.txt")).unwrap());
+ let expected_stream = BufReader::new(File::open(base.join(name)).unwrap());
+ let format = Format::new(type_, 40, 1).unwrap();
+ let settings = Settings::global().formats.number_style(type_);
+ println!("{:?}", settings);
for (line_number, (input, expected)) in input_stream
.lines()
.map(|result| result.unwrap())
.enumerate()
{
let line_number = line_number + 1;
- let expected = expected.as_bytes()[1..].chunks(10).collect::<Vec<_>>();
- assert_eq!(
- expected.len(),
- 6,
- "num-in.expected.line:{line_number}: {expected:?}"
- );
-
- let expected = expected
- .into_iter()
- .map(|s| from_utf8(s).unwrap())
- .collect::<Vec<_>>();
- let f = Format::new(Type::F, 40, 1).unwrap();
- let value = f
- .parser()
- .parse(&input, UTF_8)
- .unwrap_or(f.default_value())
+ let result = format.parser().parse(&input, UTF_8);
+ let error = result.clone().err();
+ let value = result
+ .unwrap_or(format.default_value())
.display(Format::new(Type::F, 10, 4).unwrap(), UTF_8)
.to_string();
- if value != expected[0] {
+ if value != expected {
panic!(
- "parsing {input:?} as {f} failed:\n got: {value:?}\nexpected: {:?}",
- expected[0],
+ "parsing {input:?} as {format} failed ({name}:{line_number}):\n got: {value:?}\nexpected: {expected:?}\ndecode error: {error:?}",
);
}
}
}
+
+ #[test]
+ fn f() {
+ test("f.txt", Type::F);
+ }
+
+ #[test]
+ fn e() {
+ test("e.txt", Type::E);
+ }
+
+ #[test]
+ fn comma() {
+ test("comma.txt", Type::Comma);
+ }
+
+ #[test]
+ fn dot() {
+ test("dot.txt", Type::Dot);
+ }
+
+ #[test]
+ fn dollar() {
+ test("dollar.txt", Type::Dollar);
+ }
+
+ #[test]
+ fn pct() {
+ test("pct.txt", Type::Pct);
+ }
}