diff --git a/prost-reflect-tests/src/text_format.rs b/prost-reflect-tests/src/text_format.rs index b8cac50b..d15fddf1 100644 --- a/prost-reflect-tests/src/text_format.rs +++ b/prost-reflect-tests/src/text_format.rs @@ -432,6 +432,27 @@ fn parse_scalars() { ); } +#[test] +fn parse_bool() { + fn parse(s: &str) -> bool { + from_text::(s).bool + } + + assert!(!parse("bool: false")); + assert!(!parse("bool: False")); + assert!(!parse("bool: f")); + assert!(!parse("bool: 0")); + assert!(!parse("bool: 00")); + assert!(!parse("bool: 0x0")); + assert!(parse("bool: true")); + assert!(parse("bool: True")); + assert!(parse("bool: t")); + assert!(parse("bool: t")); + assert!(parse("bool: 1")); + assert!(parse("bool: 01")); + assert!(parse("bool: 0x1")); +} + #[test] fn parse_scalars_float_extrema() { assert_eq!( @@ -684,14 +705,19 @@ fn parse_error() { error("fixed64: BAR"), "expected an integer, but found 'BAR'" ); - assert_eq!( - error("bool: 1"), - "expected 'true' or 'false', but found '1'" - ); assert_eq!( error("bool: TRUE"), "expected 'true' or 'false', but found 'TRUE'" ); + assert_eq!( + error("bool: tRuE"), + "expected 'true' or 'false', but found 'tRuE'" + ); + assert_eq!(error("bool: 3"), "expected 0 or 1, but found '3'"); + assert_eq!( + error("bool: 99999999999999"), + "expected 0 or 1, but found '99999999999999'" + ); assert_eq!(error("bytes: 1.2"), "expected a string, but found '1.2'"); assert_eq!(error("bytes: TRUE"), "expected a string, but found 'TRUE'"); assert_eq!(error("bytes: '\\x'"), "invalid string escape"); diff --git a/prost-reflect/src/dynamic/text_format/parse/mod.rs b/prost-reflect/src/dynamic/text_format/parse/mod.rs index db4c69ba..5354224e 100644 --- a/prost-reflect/src/dynamic/text_format/parse/mod.rs +++ b/prost-reflect/src/dynamic/text_format/parse/mod.rs @@ -481,8 +481,25 @@ impl<'a> Parser<'a> { fn parse_bool(&mut self) -> Result<(bool, Span), ParseErrorKind> { match self.peek()? { - Some((Token::Ident("false"), _)) => Ok((false, self.bump())), - Some((Token::Ident("true"), _)) => Ok((true, self.bump())), + Some((Token::Ident("false"), _)) + | Some((Token::Ident("False"), _)) + | Some((Token::Ident("f"), _)) => Ok((false, self.bump())), + Some((Token::Ident("true"), _)) + | Some((Token::Ident("True"), _)) + | Some((Token::Ident("t"), _)) => Ok((true, self.bump())), + Some((Token::IntLiteral(v), _)) => { + let value = match u8::from_str_radix(v.value, v.radix) { + Ok(v) => v, + Err(_e) => return self.unexpected_token("0 or 1"), + }; + if value == 1 { + Ok((true, self.bump())) + } else if value == 0 { + Ok((false, self.bump())) + } else { + self.unexpected_token("0 or 1") + } + } _ => self.unexpected_token("'true' or 'false'"), } }