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