1use crate::error::{Error, Result};
7use std::collections::BTreeMap;
8use std::fmt;
9
10#[derive(Debug, Clone, PartialEq)]
12pub enum Value {
13 Null,
15 Bool(bool),
17 Integer(i64),
19 Float(f64),
21 String(String),
23 Array(Vec<Value>),
25 Table(BTreeMap<String, Value>),
27}
28
29impl Value {
30 pub fn null() -> Self {
32 Value::Null
33 }
34
35 pub fn bool(value: bool) -> Self {
37 Value::Bool(value)
38 }
39
40 pub fn integer(value: i64) -> Self {
42 Value::Integer(value)
43 }
44
45 pub fn float(value: f64) -> Self {
47 Value::Float(value)
48 }
49
50 pub fn string<S: Into<String>>(value: S) -> Self {
52 Value::String(value.into())
53 }
54
55 pub fn array(values: Vec<Value>) -> Self {
57 Value::Array(values)
58 }
59
60 pub fn table(table: BTreeMap<String, Value>) -> Self {
62 Value::Table(table)
63 }
64
65 pub fn type_name(&self) -> &'static str {
67 match self {
68 Value::Null => "null",
69 Value::Bool(_) => "bool",
70 Value::Integer(_) => "integer",
71 Value::Float(_) => "float",
72 Value::String(_) => "string",
73 Value::Array(_) => "array",
74 Value::Table(_) => "table",
75 }
76 }
77
78 pub fn is_null(&self) -> bool {
80 matches!(self, Value::Null)
81 }
82
83 pub fn is_bool(&self) -> bool {
85 matches!(self, Value::Bool(_))
86 }
87
88 pub fn is_integer(&self) -> bool {
90 matches!(self, Value::Integer(_))
91 }
92
93 pub fn is_float(&self) -> bool {
95 matches!(self, Value::Float(_))
96 }
97
98 pub fn is_string(&self) -> bool {
100 matches!(self, Value::String(_))
101 }
102
103 pub fn is_array(&self) -> bool {
105 matches!(self, Value::Array(_))
106 }
107
108 pub fn is_table(&self) -> bool {
110 matches!(self, Value::Table(_))
111 }
112
113 pub fn as_bool(&self) -> Result<bool> {
115 match self {
116 Value::Bool(b) => Ok(*b),
117 Value::String(s) => {
118 match s.to_lowercase().as_str() {
119 "true" | "yes" | "1" | "on" => Ok(true),
120 "false" | "no" | "0" | "off" => Ok(false),
121 _ => Err(Error::type_error(
122 "Cannot convert to boolean",
123 "bool",
124 self.type_name(),
125 )),
126 }
127 },
128 _ => Err(Error::type_error(
129 "Cannot convert to boolean",
130 "bool",
131 self.type_name(),
132 )),
133 }
134 }
135
136 pub fn as_integer(&self) -> Result<i64> {
138 match self {
139 Value::Integer(i) => Ok(*i),
140 Value::Float(f) => Ok(*f as i64),
141 Value::String(s) => s.parse::<i64>().map_err(|_| Error::type_error(
142 "Cannot convert to integer",
143 "integer",
144 self.type_name(),
145 )),
146 _ => Err(Error::type_error(
147 "Cannot convert to integer",
148 "integer",
149 self.type_name(),
150 )),
151 }
152 }
153
154 pub fn as_float(&self) -> Result<f64> {
156 match self {
157 Value::Float(f) => Ok(*f),
158 Value::Integer(i) => Ok(*i as f64),
159 Value::String(s) => s.parse::<f64>().map_err(|_| Error::type_error(
160 "Cannot convert to float",
161 "float",
162 self.type_name(),
163 )),
164 _ => Err(Error::type_error(
165 "Cannot convert to float",
166 "float",
167 self.type_name(),
168 )),
169 }
170 }
171
172 pub fn as_string(&self) -> Result<&str> {
174 match self {
175 Value::String(s) => Ok(s.as_str()),
176 _ => Err(Error::type_error(
177 "Cannot convert to string",
178 "string",
179 self.type_name(),
180 )),
181 }
182 }
183
184 pub fn to_string_representation(&self) -> Result<String> {
186 match self {
187 Value::String(s) => Ok(s.clone()),
188 Value::Integer(i) => Ok(i.to_string()),
189 Value::Float(f) => Ok(f.to_string()),
190 Value::Bool(b) => Ok(b.to_string()),
191 _ => Err(Error::type_error(
192 "Cannot convert to string representation",
193 "string",
194 self.type_name(),
195 )),
196 }
197 }
198
199 pub fn as_array(&self) -> Result<&Vec<Value>> {
201 match self {
202 Value::Array(arr) => Ok(arr),
203 _ => Err(Error::type_error(
204 "Cannot convert to array",
205 "array",
206 self.type_name(),
207 )),
208 }
209 }
210
211 pub fn as_array_mut(&mut self) -> Result<&mut Vec<Value>> {
213 match self {
214 Value::Array(arr) => Ok(arr),
215 _ => Err(Error::type_error(
216 "Cannot convert to array",
217 "array",
218 self.type_name(),
219 )),
220 }
221 }
222
223 pub fn as_table(&self) -> Result<&BTreeMap<String, Value>> {
225 match self {
226 Value::Table(table) => Ok(table),
227 _ => Err(Error::type_error(
228 "Cannot convert to table",
229 "table",
230 self.type_name(),
231 )),
232 }
233 }
234
235 pub fn as_table_mut(&mut self) -> Result<&mut BTreeMap<String, Value>> {
237 match self {
238 Value::Table(table) => Ok(table),
239 _ => Err(Error::type_error(
240 "Cannot convert to table",
241 "table",
242 self.type_name(),
243 )),
244 }
245 }
246
247 pub fn get(&self, path: &str) -> Option<&Value> {
249 if path.is_empty() {
250 return Some(self);
251 }
252
253 let parts: Vec<&str> = path.split('.').collect();
254 let mut current = self;
255
256 for part in parts {
257 match current {
258 Value::Table(table) => {
259 current = table.get(part)?;
260 }
261 _ => return None,
262 }
263 }
264
265 Some(current)
266 }
267
268 pub fn get_mut_nested(&mut self, path: &str) -> Result<&mut Value> {
270 if path.is_empty() {
271 return Ok(self);
272 }
273
274 let parts: Vec<&str> = path.split('.').collect();
275 if parts.is_empty() {
276 return Err(Error::key_not_found(path));
277 }
278
279 let (last_key, parent_path) = parts.split_last()
280 .ok_or_else(|| Error::key_not_found(path))?;
281
282 let mut current = self;
284 for part in parent_path {
285 match current {
286 Value::Table(table) => {
287 current = table.get_mut(*part)
288 .ok_or_else(|| Error::key_not_found(*part))?;
289 }
290 _ => return Err(Error::type_error(
291 format!("Cannot navigate into {} when looking for key '{}'", current.type_name(), part),
292 "table",
293 current.type_name(),
294 )),
295 }
296 }
297
298 match current {
300 Value::Table(table) => {
301 table.get_mut(*last_key)
302 .ok_or_else(|| Error::key_not_found(*last_key))
303 }
304 _ => Err(Error::type_error(
305 format!("Cannot get key '{}' from {}", last_key, current.type_name()),
306 "table",
307 current.type_name(),
308 )),
309 }
310 }
311
312 pub fn set_nested(&mut self, path: &str, value: Value) -> Result<()> {
314 if path.is_empty() {
315 return Err(Error::key_not_found(""));
316 }
317
318 let parts: Vec<&str> = path.split('.').collect();
319 if parts.is_empty() {
320 return Err(Error::key_not_found(path));
321 }
322
323 let (last_key, parent_path) = parts.split_last()
324 .ok_or_else(|| Error::key_not_found(path))?;
325
326 let mut current = self;
328 for part in parent_path {
329 if let Value::Table(table) = current {
330 let entry = table.entry(part.to_string()).or_insert_with(|| {
332 Value::table(BTreeMap::new())
333 });
334 current = entry;
335 } else {
336 return Err(Error::type_error(
337 format!("Cannot navigate into {}", current.type_name()),
338 "table",
339 current.type_name(),
340 ));
341 }
342 }
343
344 if let Value::Table(table) = current {
346 table.insert(last_key.to_string(), value);
347 Ok(())
348 } else {
349 Err(Error::type_error(
350 format!("Cannot set key in {}", current.type_name()),
351 "table",
352 current.type_name(),
353 ))
354 }
355 }
356
357 pub fn remove(&mut self, path: &str) -> Result<Option<Value>> {
359 if path.is_empty() {
360 let old = std::mem::replace(self, Value::Null);
361 return Ok(Some(old));
362 }
363
364 let parts: Vec<&str> = path.split('.').collect();
365 if parts.is_empty() {
366 return Err(Error::key_not_found(path));
367 }
368
369 let (last_key, parent_path) = parts.split_last()
370 .ok_or_else(|| Error::key_not_found(path))?;
371
372 let mut current = self;
374 for part in parent_path {
375 match current {
376 Value::Table(table) => {
377 current = table.get_mut(*part)
378 .ok_or_else(|| Error::key_not_found(*part))?;
379 }
380 _ => return Err(Error::type_error(
381 format!("Cannot navigate into {} when removing key '{}'", current.type_name(), part),
382 "table",
383 current.type_name(),
384 )),
385 }
386 }
387
388 if let Value::Table(table) = current {
390 Ok(table.remove(*last_key))
391 } else {
392 Err(Error::type_error(
393 format!("Cannot remove key '{}' from {}", last_key, current.type_name()),
394 "table",
395 current.type_name(),
396 ))
397 }
398 }
399
400 pub fn keys(&self) -> Result<Vec<&str>> {
402 match self {
403 Value::Table(table) => Ok(table.keys().map(|k| k.as_str()).collect()),
404 _ => Err(Error::type_error(
405 "Cannot get keys from non-table value",
406 "table",
407 self.type_name(),
408 )),
409 }
410 }
411
412 pub fn contains_key(&self, path: &str) -> bool {
414 self.get(path).is_some()
415 }
416
417 pub fn set(&mut self, path: &str, value: Value) -> Result<()> {
419 self.set_nested(path, value)
420 }
421
422 pub fn len(&self) -> usize {
424 match self {
425 Value::Array(arr) => arr.len(),
426 Value::Table(table) => table.len(),
427 Value::String(s) => s.len(),
428 _ => 0,
429 }
430 }
431
432 pub fn is_empty(&self) -> bool {
434 self.len() == 0
435 }
436}
437
438impl fmt::Display for Value {
439 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
440 match self {
441 Value::Null => write!(f, "null"),
442 Value::Bool(b) => write!(f, "{}", b),
443 Value::Integer(i) => write!(f, "{}", i),
444 Value::Float(fl) => write!(f, "{}", fl),
445 Value::String(s) => write!(f, "{}", s),
446 Value::Array(arr) => {
447 write!(f, "[")?;
448 for (i, item) in arr.iter().enumerate() {
449 if i > 0 {
450 write!(f, ", ")?;
451 }
452 write!(f, "{}", item)?;
453 }
454 write!(f, "]")
455 }
456 Value::Table(table) => {
457 write!(f, "{{")?;
458 for (i, (key, value)) in table.iter().enumerate() {
459 if i > 0 {
460 write!(f, ", ")?;
461 }
462 write!(f, "{}: {}", key, value)?;
463 }
464 write!(f, "}}")
465 }
466 }
467 }
468}
469
470impl From<bool> for Value {
472 fn from(value: bool) -> Self {
473 Value::Bool(value)
474 }
475}
476
477impl From<i32> for Value {
478 fn from(value: i32) -> Self {
479 Value::Integer(value as i64)
480 }
481}
482
483impl From<i64> for Value {
484 fn from(value: i64) -> Self {
485 Value::Integer(value)
486 }
487}
488
489impl From<f32> for Value {
490 fn from(value: f32) -> Self {
491 Value::Float(value as f64)
492 }
493}
494
495impl From<f64> for Value {
496 fn from(value: f64) -> Self {
497 Value::Float(value)
498 }
499}
500
501impl From<String> for Value {
502 fn from(value: String) -> Self {
503 Value::String(value)
504 }
505}
506
507impl From<&str> for Value {
508 fn from(value: &str) -> Self {
509 Value::String(value.to_string())
510 }
511}
512
513impl From<Vec<Value>> for Value {
514 fn from(value: Vec<Value>) -> Self {
515 Value::Array(value)
516 }
517}
518
519impl From<BTreeMap<String, Value>> for Value {
520 fn from(value: BTreeMap<String, Value>) -> Self {
521 Value::Table(value)
522 }
523}
524
525impl Value {
527 pub fn string_from_slice(value: &str) -> Self {
529 Value::String(value.to_string())
530 }
531
532 pub fn as_str(&self) -> Result<&str> {
534 match self {
535 Value::String(s) => Ok(s.as_str()),
536 _ => Err(Error::type_error(
537 "Value is not a string",
538 "string",
539 self.type_name(),
540 )),
541 }
542 }
543}
544
545#[cfg(test)]
546mod tests {
547 use super::*;
548
549 #[test]
550 fn test_value_creation() {
551 assert_eq!(Value::null(), Value::Null);
552 assert_eq!(Value::bool(true), Value::Bool(true));
553 assert_eq!(Value::integer(42), Value::Integer(42));
554 assert_eq!(Value::float(3.14), Value::Float(3.14));
555 assert_eq!(Value::string("test"), Value::String("test".to_string()));
556 }
557
558 #[test]
559 fn test_type_checking() {
560 let null = Value::null();
561 let bool_val = Value::bool(true);
562 let int_val = Value::integer(42);
563 let float_val = Value::float(3.14);
564 let string_val = Value::string("test");
565 let array_val = Value::array(vec![Value::integer(1), Value::integer(2)]);
566 let table_val = Value::table(BTreeMap::new());
567
568 assert!(null.is_null());
569 assert!(bool_val.is_bool());
570 assert!(int_val.is_integer());
571 assert!(float_val.is_float());
572 assert!(string_val.is_string());
573 assert!(array_val.is_array());
574 assert!(table_val.is_table());
575 }
576
577 #[test]
578 fn test_value_conversion() {
579 let bool_val = Value::bool(true);
580 let int_val = Value::integer(42);
581 let float_val = Value::float(3.14);
582 let string_val = Value::string("test");
583
584 assert_eq!(bool_val.as_bool().unwrap(), true);
585 assert_eq!(int_val.as_integer().unwrap(), 42);
586 assert_eq!(float_val.as_float().unwrap(), 3.14);
587 assert_eq!(string_val.as_string().unwrap(), "test");
588 }
589
590 #[test]
591 fn test_nested_access() {
592 let mut table = BTreeMap::new();
593 let mut inner_table = BTreeMap::new();
594 inner_table.insert("inner_key".to_string(), Value::string("inner_value"));
595 table.insert("outer_key".to_string(), Value::table(inner_table));
596
597 let value = Value::table(table);
598
599 assert_eq!(
600 value.get("outer_key.inner_key").unwrap().as_string().unwrap(),
601 "inner_value"
602 );
603 }
604
605 #[test]
606 fn test_enterprise_error_handling() {
607 let mut value = Value::table(BTreeMap::new());
608
609 assert!(value.get_mut_nested("nonexistent.key").is_err());
611 assert!(value.remove("nonexistent.key").is_err());
612
613 assert!(value.set_nested("test.key", Value::string("value")).is_ok());
615 assert!(value.get("test.key").is_some());
616 }
617}