reifydb_type/value/boolean/
parse.rs1use crate::{
5 err,
6 error::{
7 Error,
8 diagnostic::boolean::{empty_boolean_value, invalid_boolean_format, invalid_number_boolean},
9 },
10 fragment::Fragment,
11 return_error,
12};
13
14pub fn parse_bool(fragment: Fragment) -> Result<bool, Error> {
15 let value = fragment.text().trim();
17
18 if value.is_empty() {
19 return_error!(empty_boolean_value(fragment));
20 }
21
22 match value.as_bytes() {
24 b"true" | b"TRUE" | b"True" => return Ok(true),
25 b"false" | b"FALSE" | b"False" => return Ok(false),
26 b"1" | b"1.0" => return Ok(true),
27 b"0" | b"0.0" => return Ok(false),
28 _ => {}
29 }
30
31 match value.len() {
33 4 if value.eq_ignore_ascii_case("true") => Ok(true),
34 5 if value.eq_ignore_ascii_case("false") => Ok(false),
35 3 if value == "1.0" => Ok(true),
36 3 if value == "0.0" => Ok(false),
37 _ => {
38 if value.as_bytes().iter().any(|&b| b.is_ascii_digit()) {
41 err!(invalid_number_boolean(fragment))
42 } else {
43 err!(invalid_boolean_format(fragment))
44 }
45 }
46 }
47}
48
49#[cfg(test)]
50pub mod tests {
51 use super::*;
52
53 #[test]
54 fn test_valid_true() {
55 assert_eq!(parse_bool(Fragment::testing("true")), Ok(true));
56 }
57
58 #[test]
59 fn test_valid_false() {
60 assert_eq!(parse_bool(Fragment::testing("false")), Ok(false));
61 }
62
63 #[test]
64 fn test_valid_true_with_spaces() {
65 assert_eq!(parse_bool(Fragment::testing(" true ")), Ok(true));
66 }
67
68 #[test]
69 fn test_valid_false_with_spaces() {
70 assert_eq!(parse_bool(Fragment::testing(" false ")), Ok(false));
71 }
72
73 #[test]
74 fn test_case_mismatch_true() {
75 assert_eq!(parse_bool(Fragment::testing("True")), Ok(true));
76 assert_eq!(parse_bool(Fragment::testing("TRUE")), Ok(true));
77 assert_eq!(parse_bool(Fragment::testing("tRuE")), Ok(true));
78 }
79
80 #[test]
81 fn test_case_mismatch_false() {
82 assert_eq!(parse_bool(Fragment::testing("False")), Ok(false));
83 assert_eq!(parse_bool(Fragment::testing("FALSE")), Ok(false));
84 assert_eq!(parse_bool(Fragment::testing("fAlSe")), Ok(false));
85 }
86
87 #[test]
88 fn test_valid_numeric_boolean() {
89 assert_eq!(parse_bool(Fragment::testing("1")), Ok(true));
90 assert_eq!(parse_bool(Fragment::testing("0")), Ok(false));
91 assert_eq!(parse_bool(Fragment::testing("1.0")), Ok(true));
92 assert_eq!(parse_bool(Fragment::testing("0.0")), Ok(false));
93 }
94
95 #[test]
96 fn test_invalid_numeric_boolean() {
97 assert!(parse_bool(Fragment::testing("2")).is_err());
98 assert!(parse_bool(Fragment::testing("1.5")).is_err());
99 assert!(parse_bool(Fragment::testing("0.5")).is_err());
100 assert!(parse_bool(Fragment::testing("-1")).is_err());
101 assert!(parse_bool(Fragment::testing("100")).is_err());
102 }
103
104 #[test]
105 fn test_empty_boolean_value() {
106 assert!(parse_bool(Fragment::testing("")).is_err());
107 assert!(parse_bool(Fragment::testing(" ")).is_err());
108 }
109
110 #[test]
111 fn test_ambiguous_boolean_value() {
112 assert!(parse_bool(Fragment::testing("yes")).is_err());
113 assert!(parse_bool(Fragment::testing("no")).is_err());
114 assert!(parse_bool(Fragment::testing("y")).is_err());
115 assert!(parse_bool(Fragment::testing("n")).is_err());
116 assert!(parse_bool(Fragment::testing("on")).is_err());
117 assert!(parse_bool(Fragment::testing("off")).is_err());
118 assert!(parse_bool(Fragment::testing("t")).is_err());
119 assert!(parse_bool(Fragment::testing("f")).is_err());
120 }
121
122 #[test]
123 fn test_invalid_boolean_format() {
124 assert!(parse_bool(Fragment::testing("invalid")).is_err());
125 assert!(parse_bool(Fragment::testing("123")).is_err());
126 assert!(parse_bool(Fragment::testing("abc")).is_err());
127 assert!(parse_bool(Fragment::testing("maybe")).is_err());
128 }
129
130 #[test]
131 fn test_case_insensitive_ambiguous() {
132 assert!(parse_bool(Fragment::testing("Yes")).is_err());
133 assert!(parse_bool(Fragment::testing("NO")).is_err());
134 assert!(parse_bool(Fragment::testing("On")).is_err());
135 assert!(parse_bool(Fragment::testing("OFF")).is_err());
136 }
137}