1use anyhow::{Result, anyhow};
12
13fn is_kv_array(data: &[String]) -> bool {
15 data.len().is_multiple_of(2)
16}
17
18pub fn kv_has_value(data: &[String], key: &str) -> bool {
19 assert!(is_kv_array(data), "kv_has_value: invalid kv array length");
22 let mut i = 0;
24 while i < data.len() {
25 if data.get(i).is_some_and(|k| k == key) {
26 return true;
27 }
28 i += 2;
29 }
30 false
31}
32
33pub fn kv_get_value(data: &[String], key: &str) -> String {
35 assert!(is_kv_array(data), "kv_get_value: invalid kv array length");
36 let mut i = 0;
37 while i + 1 < data.len() {
38 if data[i] == key {
39 return data[i + 1].clone();
40 }
41 i += 2;
42 }
43 String::new()
44}
45
46pub fn kv_get_defined_value(data: &[String], key: &str) -> Result<String> {
48 if kv_has_value(data, key) {
49 Ok(kv_get_value(data, key))
50 } else {
51 Err(anyhow!("Key '{key}' not found"))
52 }
53}
54
55pub fn kv_set_value(
57 mut data: Vec<String>,
58 key: &str,
59 val: &str,
60) -> Vec<String> {
61 assert!(is_kv_array(&data), "kv_set_value: invalid kv array length");
62 let mut i = 0;
63 while i + 1 < data.len() {
64 if data[i] == key {
65 data[i + 1] = val.to_string();
66 return data;
67 }
68 i += 2;
69 }
70 data.push(key.to_string());
71 data.push(val.to_string());
72 data
73}
74
75#[cfg(test)]
76pub mod tests {
77 use super::*;
78
79 #[crate::ctb_test]
80 fn test_kv_basic() {
81 let data: Vec<String> = vec![];
82 let data = kv_set_value(data, "a", "1");
83 let data = kv_set_value(data, "b", "2");
84 assert!(kv_has_value(&data, "a"));
85 assert_eq!(kv_get_value(&data, "a"), "1");
86 assert_eq!(kv_get_value(&data, "c"), "");
87 let data = kv_set_value(data, "a", "3");
88 assert_eq!(kv_get_value(&data, "a"), "3");
89 }
90
91 #[crate::ctb_test]
92 fn test_kv_has_value_empty_and_odd_length() {
93 let data: Vec<String> = vec![];
94 assert!(!kv_has_value(&data, "x"));
95 let data = vec!["a".to_string()];
96 let result = std::panic::catch_unwind(|| kv_has_value(&data, "a"));
97 assert!(result.is_err());
98 }
99
100 #[crate::ctb_test]
101 fn test_kv_get_value_empty_and_odd_length() {
102 let data: Vec<String> = vec![];
103 assert_eq!(kv_get_value(&data, "x"), "");
104 let data = vec!["a".to_string()];
105 let result = std::panic::catch_unwind(|| kv_get_value(&data, "a"));
106 assert!(result.is_err());
107 }
108
109 #[crate::ctb_test]
110 fn test_kv_get_defined_value_found_and_not_found() {
111 let mut data: Vec<String> = vec![];
112 data = kv_set_value(data, "foo", "bar");
113 assert_eq!(kv_get_defined_value(&data, "foo").unwrap(), "bar");
114 let err = kv_get_defined_value(&data, "baz");
115 assert!(err.is_err());
116 }
117
118 #[crate::ctb_test]
119 fn test_kv_set_value_insert_and_replace() {
120 let mut data: Vec<String> = vec![];
121 data = kv_set_value(data, "x", "1");
122 assert_eq!(data, vec!["x", "1"]);
123 assert_eq!(kv_get_value(&data, "x"), "1");
124 data = kv_set_value(data, "x", "2");
125 assert_eq!(data, vec!["x", "2"]);
126 assert_eq!(kv_get_value(&data, "x"), "2");
127 }
128
129 #[crate::ctb_test]
130 fn test_kv_set_value_odd_length_panics() {
131 let data = vec!["a".to_string()];
132 let result = std::panic::catch_unwind(|| kv_set_value(data, "b", "2"));
133 assert!(result.is_err());
134 }
135
136 #[crate::ctb_test]
137 fn test_kv_array_get_set_mid_elements() {
138 let mut data = vec![
139 "k1".to_string(),
140 "v1".to_string(),
141 "k2".to_string(),
142 "v2".to_string(),
143 "k3".to_string(),
144 "v3".to_string(),
145 "k4".to_string(),
146 "v4".to_string(),
147 ];
148 assert_eq!(kv_get_value(&data, "k2"), "v2");
150 assert_eq!(kv_get_value(&data, "k3"), "v3");
151 data = kv_set_value(data, "k2", "v2x");
153 assert_eq!(kv_get_value(&data, "k2"), "v2x");
154 data = kv_set_value(data, "k5", "v5");
156 assert_eq!(kv_get_value(&data, "k5"), "v5");
157 assert_eq!(
159 data,
160 vec!["k1", "v1", "k2", "v2x", "k3", "v3", "k4", "v4", "k5", "v5"]
161 );
162 }
163
164 #[crate::ctb_test]
165 fn test_kv_array_get_set_first_and_last() {
166 let mut data = vec![
167 "a".to_string(),
168 "1".to_string(),
169 "b".to_string(),
170 "2".to_string(),
171 "c".to_string(),
172 "3".to_string(),
173 "d".to_string(),
174 "4".to_string(),
175 ];
176 assert_eq!(kv_get_value(&data, "a"), "1");
178 assert_eq!(kv_get_value(&data, "d"), "4");
179 data = kv_set_value(data, "d", "44");
181 assert_eq!(kv_get_value(&data, "d"), "44");
182 data = kv_set_value(data, "a", "11");
184 assert_eq!(kv_get_value(&data, "a"), "11");
185 assert_eq!(data, vec!["a", "11", "b", "2", "c", "3", "d", "44"]);
187 }
188}