1 use nom::branch::alt;
2 use nom::bytes::complete::tag;
3 use nom::character::streaming::digit1 as digit;
4 use nom::combinator::{map, map_res, opt, recognize};
5 use nom::sequence::{delimited, pair};
6 use nom::IResult;
7
8 use std::str;
9 use std::str::FromStr;
10
unsigned_float(i: &[u8]) -> IResult<&[u8], f32>11 fn unsigned_float(i: &[u8]) -> IResult<&[u8], f32> {
12 let float_bytes = recognize(alt((
13 delimited(digit, tag("."), opt(digit)),
14 delimited(opt(digit), tag("."), digit),
15 )));
16 let float_str = map_res(float_bytes, str::from_utf8);
17 map_res(float_str, FromStr::from_str)(i)
18 }
19
float(i: &[u8]) -> IResult<&[u8], f32>20 fn float(i: &[u8]) -> IResult<&[u8], f32> {
21 map(
22 pair(opt(alt((tag("+"), tag("-")))), unsigned_float),
23 |(sign, value)| {
24 sign
25 .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None })
26 .unwrap_or(1f32)
27 * value
28 },
29 )(i)
30 }
31
32 #[test]
unsigned_float_test()33 fn unsigned_float_test() {
34 assert_eq!(unsigned_float(&b"123.456;"[..]), Ok((&b";"[..], 123.456)));
35 assert_eq!(unsigned_float(&b"0.123;"[..]), Ok((&b";"[..], 0.123)));
36 assert_eq!(unsigned_float(&b"123.0;"[..]), Ok((&b";"[..], 123.0)));
37 assert_eq!(unsigned_float(&b"123.;"[..]), Ok((&b";"[..], 123.0)));
38 assert_eq!(unsigned_float(&b".123;"[..]), Ok((&b";"[..], 0.123)));
39 }
40
41 #[test]
float_test()42 fn float_test() {
43 assert_eq!(float(&b"123.456;"[..]), Ok((&b";"[..], 123.456)));
44 assert_eq!(float(&b"+123.456;"[..]), Ok((&b";"[..], 123.456)));
45 assert_eq!(float(&b"-123.456;"[..]), Ok((&b";"[..], -123.456)));
46 }
47