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