1use base64::{engine::general_purpose::STANDARD, Engine as _};
12use indexmap::IndexMap;
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14use std::fmt;
15use std::io::Read;
16
17use crate::error::{Error, Result};
18
19#[derive(Default)]
24pub enum Value {
25 #[default]
27 Null,
28 Bool(bool),
30 Integer(i64),
32 Float(f64),
34 String(String),
36 Bytes(Vec<u8>),
38 Stream(Box<dyn Read + Send + Sync>),
42 Sequence(Vec<Value>),
44 Mapping(IndexMap<String, Value>),
46}
47
48impl fmt::Debug for Value {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self {
52 Value::Null => write!(f, "Null"),
53 Value::Bool(b) => f.debug_tuple("Bool").field(b).finish(),
54 Value::Integer(i) => f.debug_tuple("Integer").field(i).finish(),
55 Value::Float(fl) => f.debug_tuple("Float").field(fl).finish(),
56 Value::String(s) => f.debug_tuple("String").field(s).finish(),
57 Value::Bytes(bytes) => f.debug_tuple("Bytes").field(bytes).finish(),
58 Value::Stream(_) => write!(f, "Stream(<stream>)"),
59 Value::Sequence(seq) => f.debug_tuple("Sequence").field(seq).finish(),
60 Value::Mapping(map) => f.debug_tuple("Mapping").field(map).finish(),
61 }
62 }
63}
64
65impl Clone for Value {
67 fn clone(&self) -> Self {
68 match self {
69 Value::Null => Value::Null,
70 Value::Bool(b) => Value::Bool(*b),
71 Value::Integer(i) => Value::Integer(*i),
72 Value::Float(f) => Value::Float(*f),
73 Value::String(s) => Value::String(s.clone()),
74 Value::Bytes(bytes) => Value::Bytes(bytes.clone()),
75 Value::Stream(_) => {
76 panic!("Cannot clone Value::Stream - must materialize() before cloning")
77 }
78 Value::Sequence(seq) => Value::Sequence(seq.clone()),
79 Value::Mapping(map) => Value::Mapping(map.clone()),
80 }
81 }
82}
83
84impl PartialEq for Value {
86 fn eq(&self, other: &Self) -> bool {
87 match (self, other) {
88 (Value::Null, Value::Null) => true,
89 (Value::Bool(a), Value::Bool(b)) => a == b,
90 (Value::Integer(a), Value::Integer(b)) => a == b,
91 (Value::Float(a), Value::Float(b)) => a == b,
92 (Value::String(a), Value::String(b)) => a == b,
93 (Value::Bytes(a), Value::Bytes(b)) => a == b,
94 (Value::Stream(_), Value::Stream(_)) => {
95 panic!("Cannot compare Value::Stream - must materialize() first")
96 }
97 (Value::Sequence(a), Value::Sequence(b)) => a == b,
98 (Value::Mapping(a), Value::Mapping(b)) => a == b,
99 _ => false,
100 }
101 }
102}
103
104impl Serialize for Value {
106 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
107 where
108 S: Serializer,
109 {
110 match self {
111 Value::Null => serializer.serialize_none(),
112 Value::Bool(b) => serializer.serialize_bool(*b),
113 Value::Integer(i) => serializer.serialize_i64(*i),
114 Value::Float(f) => serializer.serialize_f64(*f),
115 Value::String(s) => serializer.serialize_str(s),
116 Value::Bytes(bytes) => {
117 let encoded = STANDARD.encode(bytes);
119 serializer.serialize_str(&encoded)
120 }
121 Value::Stream(_) => {
122 Err(serde::ser::Error::custom(
124 "Cannot serialize Value::Stream - must materialize() first",
125 ))
126 }
127 Value::Sequence(seq) => seq.serialize(serializer),
128 Value::Mapping(map) => map.serialize(serializer),
129 }
130 }
131}
132
133impl<'de> Deserialize<'de> for Value {
135 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
136 where
137 D: Deserializer<'de>,
138 {
139 #[derive(Deserialize)]
142 #[serde(untagged)]
143 enum ValueHelper {
144 Null,
145 Bool(bool),
146 Integer(i64),
147 Float(f64),
148 String(String),
149 Sequence(Vec<Value>),
150 Mapping(IndexMap<String, Value>),
151 }
152
153 match ValueHelper::deserialize(deserializer)? {
154 ValueHelper::Null => Ok(Value::Null),
155 ValueHelper::Bool(b) => Ok(Value::Bool(b)),
156 ValueHelper::Integer(i) => Ok(Value::Integer(i)),
157 ValueHelper::Float(f) => Ok(Value::Float(f)),
158 ValueHelper::String(s) => Ok(Value::String(s)),
159 ValueHelper::Sequence(seq) => Ok(Value::Sequence(seq)),
160 ValueHelper::Mapping(map) => Ok(Value::Mapping(map)),
161 }
162 }
163}
164
165impl Value {
166 pub fn is_null(&self) -> bool {
168 matches!(self, Value::Null)
169 }
170
171 pub fn is_bool(&self) -> bool {
173 matches!(self, Value::Bool(_))
174 }
175
176 pub fn is_integer(&self) -> bool {
178 matches!(self, Value::Integer(_))
179 }
180
181 pub fn is_float(&self) -> bool {
183 matches!(self, Value::Float(_))
184 }
185
186 pub fn is_string(&self) -> bool {
188 matches!(self, Value::String(_))
189 }
190
191 pub fn is_sequence(&self) -> bool {
193 matches!(self, Value::Sequence(_))
194 }
195
196 pub fn is_mapping(&self) -> bool {
198 matches!(self, Value::Mapping(_))
199 }
200
201 pub fn is_bytes(&self) -> bool {
203 matches!(self, Value::Bytes(_))
204 }
205
206 pub fn is_stream(&self) -> bool {
208 matches!(self, Value::Stream(_))
209 }
210
211 pub fn as_bool(&self) -> Option<bool> {
213 match self {
214 Value::Bool(b) => Some(*b),
215 _ => None,
216 }
217 }
218
219 pub fn as_i64(&self) -> Option<i64> {
221 match self {
222 Value::Integer(i) => Some(*i),
223 _ => None,
224 }
225 }
226
227 pub fn as_f64(&self) -> Option<f64> {
229 match self {
230 Value::Float(f) => Some(*f),
231 Value::Integer(i) => Some(*i as f64),
232 _ => None,
233 }
234 }
235
236 pub fn as_str(&self) -> Option<&str> {
238 match self {
239 Value::String(s) => Some(s),
240 _ => None,
241 }
242 }
243
244 pub fn as_sequence(&self) -> Option<&[Value]> {
246 match self {
247 Value::Sequence(s) => Some(s),
248 _ => None,
249 }
250 }
251
252 pub fn as_mapping(&self) -> Option<&IndexMap<String, Value>> {
254 match self {
255 Value::Mapping(m) => Some(m),
256 _ => None,
257 }
258 }
259
260 pub fn as_bytes(&self) -> Option<&[u8]> {
262 match self {
263 Value::Bytes(b) => Some(b),
264 _ => None,
265 }
266 }
267
268 pub fn get_path(&self, path: &str) -> Result<&Value> {
270 if path.is_empty() {
271 return Ok(self);
272 }
273
274 let segments = parse_path(path)?;
275 let mut current = self;
276
277 for segment in &segments {
278 current = match segment {
279 PathSegment::Key(key) => match current {
280 Value::Mapping(map) => map
281 .get(key.as_str())
282 .ok_or_else(|| Error::path_not_found(path))?,
283 _ => return Err(Error::path_not_found(path)),
284 },
285 PathSegment::Index(idx) => match current {
286 Value::Sequence(seq) => {
287 seq.get(*idx).ok_or_else(|| Error::path_not_found(path))?
288 }
289 _ => return Err(Error::path_not_found(path)),
290 },
291 };
292 }
293
294 Ok(current)
295 }
296
297 pub fn get_path_mut(&mut self, path: &str) -> Result<&mut Value> {
299 if path.is_empty() {
300 return Ok(self);
301 }
302
303 let segments = parse_path(path)?;
304 let mut current = self;
305
306 for segment in segments {
307 current = match segment {
308 PathSegment::Key(key) => match current {
309 Value::Mapping(map) => map
310 .get_mut(&key)
311 .ok_or_else(|| Error::path_not_found(path))?,
312 _ => return Err(Error::path_not_found(path)),
313 },
314 PathSegment::Index(idx) => match current {
315 Value::Sequence(seq) => seq
316 .get_mut(idx)
317 .ok_or_else(|| Error::path_not_found(path))?,
318 _ => return Err(Error::path_not_found(path)),
319 },
320 };
321 }
322
323 Ok(current)
324 }
325
326 pub fn set_path(&mut self, path: &str, value: Value) -> Result<()> {
328 if path.is_empty() {
329 *self = value;
330 return Ok(());
331 }
332
333 let segments = parse_path(path)?;
334 let mut current = self;
335
336 for (i, segment) in segments.iter().enumerate() {
337 let is_last = i == segments.len() - 1;
338
339 if is_last {
340 match segment {
341 PathSegment::Key(key) => {
342 if let Value::Mapping(map) = current {
343 map.insert(key.clone(), value);
344 return Ok(());
345 }
346 return Err(Error::path_not_found(path));
347 }
348 PathSegment::Index(idx) => {
349 if let Value::Sequence(seq) = current {
350 if *idx < seq.len() {
351 seq[*idx] = value;
352 return Ok(());
353 }
354 }
355 return Err(Error::path_not_found(path));
356 }
357 }
358 }
359
360 current = match segment {
362 PathSegment::Key(key) => {
363 if let Value::Mapping(map) = current {
364 let next_is_index = segments
366 .get(i + 1)
367 .map(|s| matches!(s, PathSegment::Index(_)))
368 .unwrap_or(false);
369
370 if !map.contains_key(key) {
371 let new_value = if next_is_index {
372 Value::Sequence(vec![])
373 } else {
374 Value::Mapping(IndexMap::new())
375 };
376 map.insert(key.clone(), new_value);
377 }
378 map.get_mut(key).unwrap()
379 } else {
380 return Err(Error::path_not_found(path));
381 }
382 }
383 PathSegment::Index(idx) => {
384 if let Value::Sequence(seq) = current {
385 seq.get_mut(*idx)
386 .ok_or_else(|| Error::path_not_found(path))?
387 } else {
388 return Err(Error::path_not_found(path));
389 }
390 }
391 };
392 }
393
394 Ok(())
395 }
396
397 pub fn type_name(&self) -> &'static str {
399 match self {
400 Value::Null => "null",
401 Value::Bool(_) => "boolean",
402 Value::Integer(_) => "integer",
403 Value::Float(_) => "float",
404 Value::String(_) => "string",
405 Value::Bytes(_) => "bytes",
406 Value::Stream(_) => "stream",
407 Value::Sequence(_) => "sequence",
408 Value::Mapping(_) => "mapping",
409 }
410 }
411
412 pub fn materialize(self) -> Result<Value> {
418 match self {
419 Value::Stream(mut reader) => {
420 let mut bytes = Vec::new();
421 reader.read_to_end(&mut bytes).map_err(|e| {
422 Error::resolver_custom("stream", format!("Failed to read stream: {}", e))
423 })?;
424 Ok(Value::Bytes(bytes))
425 }
426 other => Ok(other),
428 }
429 }
430
431 pub fn merge(&mut self, other: Value) {
440 match (self, other) {
441 (Value::Mapping(base), Value::Mapping(overlay)) => {
443 for (key, overlay_value) in overlay {
444 if overlay_value.is_null() {
445 base.shift_remove(&key);
447 } else if let Some(base_value) = base.get_mut(&key) {
448 base_value.merge(overlay_value);
450 } else {
451 base.insert(key, overlay_value);
453 }
454 }
455 }
456 (this, other) => {
458 *this = other;
459 }
460 }
461 }
462
463 pub fn merged(mut self, other: Value) -> Value {
465 self.merge(other);
466 self
467 }
468
469 pub fn merge_tracking_sources(
474 &mut self,
475 other: Value,
476 source: &str,
477 path_prefix: &str,
478 sources: &mut std::collections::HashMap<String, String>,
479 ) {
480 match (self, other) {
481 (Value::Mapping(base), Value::Mapping(overlay)) => {
483 for (key, overlay_value) in overlay {
484 let full_path = if path_prefix.is_empty() {
485 key.clone()
486 } else {
487 format!("{}.{}", path_prefix, key)
488 };
489
490 if overlay_value.is_null() {
491 base.shift_remove(&key);
493 remove_sources_with_prefix(sources, &full_path);
494 } else if let Some(base_value) = base.get_mut(&key) {
495 base_value.merge_tracking_sources(
497 overlay_value,
498 source,
499 &full_path,
500 sources,
501 );
502 } else {
503 collect_leaf_paths(&overlay_value, &full_path, source, sources);
505 base.insert(key, overlay_value);
506 }
507 }
508 }
509 (this, other) => {
511 remove_sources_with_prefix(sources, path_prefix);
513 collect_leaf_paths(&other, path_prefix, source, sources);
515 *this = other;
516 }
517 }
518 }
519
520 pub fn collect_leaf_paths(
522 &self,
523 path_prefix: &str,
524 source: &str,
525 sources: &mut std::collections::HashMap<String, String>,
526 ) {
527 collect_leaf_paths(self, path_prefix, source, sources);
528 }
529}
530
531fn collect_leaf_paths(
533 value: &Value,
534 path_prefix: &str,
535 source: &str,
536 sources: &mut std::collections::HashMap<String, String>,
537) {
538 match value {
539 Value::Mapping(map) => {
540 for (key, val) in map {
541 let full_path = if path_prefix.is_empty() {
542 key.clone()
543 } else {
544 format!("{}.{}", path_prefix, key)
545 };
546 collect_leaf_paths(val, &full_path, source, sources);
547 }
548 }
549 Value::Sequence(seq) => {
550 for (i, val) in seq.iter().enumerate() {
551 let full_path = format!("{}[{}]", path_prefix, i);
552 collect_leaf_paths(val, &full_path, source, sources);
553 }
554 }
555 _ => {
557 if !path_prefix.is_empty() {
558 sources.insert(path_prefix.to_string(), source.to_string());
559 }
560 }
561 }
562}
563
564fn remove_sources_with_prefix(
566 sources: &mut std::collections::HashMap<String, String>,
567 prefix: &str,
568) {
569 if prefix.is_empty() {
570 sources.clear();
571 return;
572 }
573 sources.retain(|path, _| {
575 path != prefix
576 && !path.starts_with(&format!("{}.", prefix))
577 && !path.starts_with(&format!("{}[", prefix))
578 });
579}
580
581impl fmt::Display for Value {
582 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583 match self {
584 Value::Null => write!(f, "null"),
585 Value::Bool(b) => write!(f, "{}", b),
586 Value::Integer(i) => write!(f, "{}", i),
587 Value::Float(n) => write!(f, "{}", n),
588 Value::String(s) => write!(f, "{}", s),
589 Value::Bytes(bytes) => write!(f, "<bytes: {} bytes>", bytes.len()),
590 Value::Stream(_) => write!(f, "<stream>"),
591 Value::Sequence(seq) => {
592 write!(f, "[")?;
593 for (i, v) in seq.iter().enumerate() {
594 if i > 0 {
595 write!(f, ", ")?;
596 }
597 write!(f, "{}", v)?;
598 }
599 write!(f, "]")
600 }
601 Value::Mapping(map) => {
602 write!(f, "{{")?;
603 for (i, (k, v)) in map.iter().enumerate() {
604 if i > 0 {
605 write!(f, ", ")?;
606 }
607 write!(f, "{}: {}", k, v)?;
608 }
609 write!(f, "}}")
610 }
611 }
612 }
613}
614
615impl From<bool> for Value {
617 fn from(b: bool) -> Self {
618 Value::Bool(b)
619 }
620}
621
622impl From<i64> for Value {
623 fn from(i: i64) -> Self {
624 Value::Integer(i)
625 }
626}
627
628impl From<i32> for Value {
629 fn from(i: i32) -> Self {
630 Value::Integer(i as i64)
631 }
632}
633
634impl From<f64> for Value {
635 fn from(f: f64) -> Self {
636 Value::Float(f)
637 }
638}
639
640impl From<String> for Value {
641 fn from(s: String) -> Self {
642 Value::String(s)
643 }
644}
645
646impl From<&str> for Value {
647 fn from(s: &str) -> Self {
648 Value::String(s.to_string())
649 }
650}
651
652impl<T: Into<Value>> From<Vec<T>> for Value {
653 fn from(v: Vec<T>) -> Self {
654 Value::Sequence(v.into_iter().map(Into::into).collect())
655 }
656}
657
658impl From<IndexMap<String, Value>> for Value {
659 fn from(m: IndexMap<String, Value>) -> Self {
660 Value::Mapping(m)
661 }
662}
663
664impl From<Vec<u8>> for Value {
665 fn from(bytes: Vec<u8>) -> Self {
666 Value::Bytes(bytes)
667 }
668}
669
670#[derive(Debug, Clone, PartialEq)]
672enum PathSegment {
673 Key(String),
675 Index(usize),
677}
678
679fn parse_path(path: &str) -> Result<Vec<PathSegment>> {
682 let mut segments = Vec::new();
683 let mut current_key = String::new();
684 let mut chars = path.chars().peekable();
685
686 while let Some(c) = chars.next() {
687 match c {
688 '.' => {
689 if !current_key.is_empty() {
690 segments.push(PathSegment::Key(current_key.clone()));
691 current_key.clear();
692 }
693 }
694 '[' => {
695 if !current_key.is_empty() {
696 segments.push(PathSegment::Key(current_key.clone()));
697 current_key.clear();
698 }
699 let mut index_str = String::new();
701 while let Some(&c) = chars.peek() {
702 if c == ']' {
703 chars.next();
704 break;
705 }
706 index_str.push(chars.next().unwrap());
707 }
708 let idx: usize = index_str.parse().map_err(|_| {
709 Error::parse(format!("Invalid array index in path: {}", index_str))
710 })?;
711 segments.push(PathSegment::Index(idx));
712 }
713 ']' => {
714 return Err(Error::parse("Unexpected ']' in path"));
715 }
716 _ => {
717 current_key.push(c);
718 }
719 }
720 }
721
722 if !current_key.is_empty() {
723 segments.push(PathSegment::Key(current_key));
724 }
725
726 Ok(segments)
727}
728
729#[cfg(test)]
730mod tests {
731 use super::*;
732
733 #[test]
734 fn test_parse_simple_path() {
735 let segments = parse_path("database").unwrap();
736 assert_eq!(segments, vec![PathSegment::Key("database".into())]);
737 }
738
739 #[test]
740 fn test_parse_dotted_path() {
741 let segments = parse_path("database.host").unwrap();
742 assert_eq!(
743 segments,
744 vec![
745 PathSegment::Key("database".into()),
746 PathSegment::Key("host".into())
747 ]
748 );
749 }
750
751 #[test]
752 fn test_parse_array_path() {
753 let segments = parse_path("servers[0]").unwrap();
754 assert_eq!(
755 segments,
756 vec![PathSegment::Key("servers".into()), PathSegment::Index(0)]
757 );
758 }
759
760 #[test]
761 fn test_parse_complex_path() {
762 let segments = parse_path("servers[0].host").unwrap();
763 assert_eq!(
764 segments,
765 vec![
766 PathSegment::Key("servers".into()),
767 PathSegment::Index(0),
768 PathSegment::Key("host".into())
769 ]
770 );
771 }
772
773 #[test]
774 fn test_value_get_path() {
775 let mut map = IndexMap::new();
776 let mut db = IndexMap::new();
777 db.insert("host".into(), Value::String("localhost".into()));
778 db.insert("port".into(), Value::Integer(5432));
779 map.insert("database".into(), Value::Mapping(db));
780
781 let value = Value::Mapping(map);
782
783 assert_eq!(
784 value.get_path("database.host").unwrap().as_str(),
785 Some("localhost")
786 );
787 assert_eq!(
788 value.get_path("database.port").unwrap().as_i64(),
789 Some(5432)
790 );
791 }
792
793 #[test]
794 fn test_value_get_path_array() {
795 let mut map = IndexMap::new();
796 map.insert(
797 "servers".into(),
798 Value::Sequence(vec![
799 Value::String("server1".into()),
800 Value::String("server2".into()),
801 ]),
802 );
803
804 let value = Value::Mapping(map);
805
806 assert_eq!(
807 value.get_path("servers[0]").unwrap().as_str(),
808 Some("server1")
809 );
810 assert_eq!(
811 value.get_path("servers[1]").unwrap().as_str(),
812 Some("server2")
813 );
814 }
815
816 #[test]
817 fn test_value_get_path_not_found() {
818 let map = IndexMap::new();
819 let value = Value::Mapping(map);
820
821 assert!(value.get_path("nonexistent").is_err());
822 }
823
824 #[test]
825 fn test_value_type_checks() {
826 assert!(Value::Null.is_null());
827 assert!(Value::Bool(true).is_bool());
828 assert!(Value::Integer(42).is_integer());
829 assert!(Value::Float(2.5).is_float());
830 assert!(Value::String("hello".into()).is_string());
831 assert!(Value::Sequence(vec![]).is_sequence());
832 assert!(Value::Mapping(IndexMap::new()).is_mapping());
833 }
834
835 #[test]
836 fn test_value_conversions() {
837 assert_eq!(Value::Bool(true).as_bool(), Some(true));
838 assert_eq!(Value::Integer(42).as_i64(), Some(42));
839 assert_eq!(Value::Float(2.5).as_f64(), Some(2.5));
840 assert_eq!(Value::Integer(42).as_f64(), Some(42.0));
841 assert_eq!(Value::String("hello".into()).as_str(), Some("hello"));
842 }
843
844 #[test]
845 fn test_merge_scalars() {
846 let mut base = Value::String("base".into());
847 base.merge(Value::String("overlay".into()));
848 assert_eq!(base.as_str(), Some("overlay"));
849 }
850
851 #[test]
852 fn test_merge_deep() {
853 let mut db_base = IndexMap::new();
855 db_base.insert("host".into(), Value::String("localhost".into()));
856 db_base.insert("port".into(), Value::Integer(5432));
857 let mut base = IndexMap::new();
858 base.insert("database".into(), Value::Mapping(db_base));
859 let mut base = Value::Mapping(base);
860
861 let mut db_overlay = IndexMap::new();
863 db_overlay.insert("host".into(), Value::String("prod-db".into()));
864 let mut overlay = IndexMap::new();
865 overlay.insert("database".into(), Value::Mapping(db_overlay));
866 let overlay = Value::Mapping(overlay);
867
868 base.merge(overlay);
869
870 assert_eq!(
872 base.get_path("database.host").unwrap().as_str(),
873 Some("prod-db")
874 );
875 assert_eq!(base.get_path("database.port").unwrap().as_i64(), Some(5432));
876 }
877
878 #[test]
879 fn test_merge_null_removes_key() {
880 let mut feature = IndexMap::new();
882 feature.insert("enabled".into(), Value::Bool(true));
883 feature.insert("config".into(), Value::String("value".into()));
884 let mut base = IndexMap::new();
885 base.insert("feature".into(), Value::Mapping(feature));
886 let mut base = Value::Mapping(base);
887
888 let mut feature_overlay = IndexMap::new();
890 feature_overlay.insert("config".into(), Value::Null);
891 let mut overlay = IndexMap::new();
892 overlay.insert("feature".into(), Value::Mapping(feature_overlay));
893 let overlay = Value::Mapping(overlay);
894
895 base.merge(overlay);
896
897 assert_eq!(
899 base.get_path("feature.enabled").unwrap().as_bool(),
900 Some(true)
901 );
902 assert!(base.get_path("feature.config").is_err());
903 }
904
905 #[test]
906 fn test_merge_array_replaces() {
907 let mut base = IndexMap::new();
909 base.insert(
910 "servers".into(),
911 Value::Sequence(vec![Value::String("a".into()), Value::String("b".into())]),
912 );
913 let mut base = Value::Mapping(base);
914
915 let mut overlay = IndexMap::new();
917 overlay.insert(
918 "servers".into(),
919 Value::Sequence(vec![Value::String("c".into())]),
920 );
921 let overlay = Value::Mapping(overlay);
922
923 base.merge(overlay);
924
925 let servers = base.get_path("servers").unwrap().as_sequence().unwrap();
927 assert_eq!(servers.len(), 1);
928 assert_eq!(servers[0].as_str(), Some("c"));
929 }
930
931 #[test]
932 fn test_merge_type_mismatch() {
933 let mut db = IndexMap::new();
935 db.insert("host".into(), Value::String("localhost".into()));
936 let mut base = IndexMap::new();
937 base.insert("database".into(), Value::Mapping(db));
938 let mut base = Value::Mapping(base);
939
940 let mut overlay = IndexMap::new();
942 overlay.insert("database".into(), Value::String("connection-string".into()));
943 let overlay = Value::Mapping(overlay);
944
945 base.merge(overlay);
946
947 assert_eq!(
949 base.get_path("database").unwrap().as_str(),
950 Some("connection-string")
951 );
952 }
953
954 #[test]
955 fn test_merge_adds_new_keys() {
956 let mut base = IndexMap::new();
958 base.insert("a".into(), Value::Integer(1));
959 let mut base = Value::Mapping(base);
960
961 let mut overlay = IndexMap::new();
963 overlay.insert("b".into(), Value::Integer(2));
964 let overlay = Value::Mapping(overlay);
965
966 base.merge(overlay);
967
968 assert_eq!(base.get_path("a").unwrap().as_i64(), Some(1));
970 assert_eq!(base.get_path("b").unwrap().as_i64(), Some(2));
971 }
972
973 #[test]
976 fn test_from_i32() {
977 let v: Value = 42i32.into();
978 assert_eq!(v, Value::Integer(42));
979 }
980
981 #[test]
982 fn test_from_vec_values() {
983 let vec: Vec<Value> = vec![Value::Integer(1), Value::Integer(2)];
984 let v: Value = vec.into();
985 assert!(v.is_sequence());
986 assert_eq!(v.as_sequence().unwrap().len(), 2);
987 }
988
989 #[test]
990 fn test_from_vec_strings() {
991 let vec: Vec<&str> = vec!["a", "b", "c"];
992 let v: Value = vec.into();
993 assert!(v.is_sequence());
994 assert_eq!(v.as_sequence().unwrap().len(), 3);
995 }
996
997 #[test]
998 fn test_from_indexmap() {
999 let mut map = IndexMap::new();
1000 map.insert("key".to_string(), Value::Integer(42));
1001 let v: Value = map.into();
1002 assert!(v.is_mapping());
1003 }
1004
1005 #[test]
1006 fn test_display_null() {
1007 assert_eq!(format!("{}", Value::Null), "null");
1008 }
1009
1010 #[test]
1011 fn test_display_bool() {
1012 assert_eq!(format!("{}", Value::Bool(true)), "true");
1013 assert_eq!(format!("{}", Value::Bool(false)), "false");
1014 }
1015
1016 #[test]
1017 fn test_display_integer() {
1018 assert_eq!(format!("{}", Value::Integer(42)), "42");
1019 assert_eq!(format!("{}", Value::Integer(-123)), "-123");
1020 }
1021
1022 #[test]
1023 fn test_display_float() {
1024 let display = format!("{}", Value::Float(1.5));
1025 assert!(display.starts_with("1.5"));
1026 }
1027
1028 #[test]
1029 fn test_display_string() {
1030 assert_eq!(format!("{}", Value::String("hello".into())), "hello");
1031 }
1032
1033 #[test]
1034 fn test_display_sequence() {
1035 let seq = Value::Sequence(vec![
1036 Value::Integer(1),
1037 Value::Integer(2),
1038 Value::Integer(3),
1039 ]);
1040 assert_eq!(format!("{}", seq), "[1, 2, 3]");
1041 }
1042
1043 #[test]
1044 fn test_display_empty_sequence() {
1045 let seq = Value::Sequence(vec![]);
1046 assert_eq!(format!("{}", seq), "[]");
1047 }
1048
1049 #[test]
1050 fn test_display_mapping() {
1051 let mut map = IndexMap::new();
1052 map.insert("a".to_string(), Value::Integer(1));
1053 let mapping = Value::Mapping(map);
1054 assert_eq!(format!("{}", mapping), "{a: 1}");
1055 }
1056
1057 #[test]
1058 fn test_display_empty_mapping() {
1059 let mapping = Value::Mapping(IndexMap::new());
1060 assert_eq!(format!("{}", mapping), "{}");
1061 }
1062
1063 #[test]
1064 fn test_as_str_non_string() {
1065 assert!(Value::Integer(42).as_str().is_none());
1066 assert!(Value::Bool(true).as_str().is_none());
1067 assert!(Value::Null.as_str().is_none());
1068 }
1069
1070 #[test]
1071 fn test_as_bool_non_bool() {
1072 assert!(Value::Integer(42).as_bool().is_none());
1073 assert!(Value::String("true".into()).as_bool().is_none());
1074 }
1075
1076 #[test]
1077 fn test_as_i64_non_integer() {
1078 assert!(Value::String("42".into()).as_i64().is_none());
1079 assert!(Value::Float(42.0).as_i64().is_none());
1080 }
1081
1082 #[test]
1083 fn test_as_f64_non_numeric() {
1084 assert!(Value::String("3.14".into()).as_f64().is_none());
1085 assert!(Value::Bool(true).as_f64().is_none());
1086 }
1087
1088 #[test]
1089 fn test_as_sequence_non_sequence() {
1090 assert!(Value::Integer(42).as_sequence().is_none());
1091 assert!(Value::Mapping(IndexMap::new()).as_sequence().is_none());
1092 }
1093
1094 #[test]
1095 fn test_as_mapping_non_mapping() {
1096 assert!(Value::Integer(42).as_mapping().is_none());
1097 assert!(Value::Sequence(vec![]).as_mapping().is_none());
1098 }
1099
1100 #[test]
1101 fn test_type_name() {
1102 assert_eq!(Value::Null.type_name(), "null");
1103 assert_eq!(Value::Bool(true).type_name(), "boolean");
1104 assert_eq!(Value::Integer(42).type_name(), "integer");
1105 assert_eq!(Value::Float(1.23).type_name(), "float");
1106 assert_eq!(Value::String("s".into()).type_name(), "string");
1107 assert_eq!(Value::Sequence(vec![]).type_name(), "sequence");
1108 assert_eq!(Value::Mapping(IndexMap::new()).type_name(), "mapping");
1109 }
1110
1111 #[test]
1112 fn test_default() {
1113 let v: Value = Default::default();
1114 assert!(v.is_null());
1115 }
1116
1117 #[test]
1118 fn test_get_path_empty() {
1119 let v = Value::Integer(42);
1120 assert_eq!(v.get_path("").unwrap(), &Value::Integer(42));
1121 }
1122
1123 #[test]
1124 fn test_get_path_on_non_mapping() {
1125 let v = Value::Integer(42);
1126 assert!(v.get_path("key").is_err());
1127 }
1128
1129 #[test]
1130 fn test_get_path_array_out_of_bounds() {
1131 let mut map = IndexMap::new();
1132 map.insert(
1133 "items".to_string(),
1134 Value::Sequence(vec![Value::Integer(1)]),
1135 );
1136 let v = Value::Mapping(map);
1137 assert!(v.get_path("items[99]").is_err());
1138 }
1139
1140 #[test]
1141 fn test_get_path_array_on_non_sequence() {
1142 let mut map = IndexMap::new();
1143 map.insert("key".to_string(), Value::Integer(42));
1144 let v = Value::Mapping(map);
1145 assert!(v.get_path("key[0]").is_err());
1146 }
1147
1148 #[test]
1149 fn test_get_path_mut_empty() {
1150 let mut v = Value::Integer(42);
1151 let result = v.get_path_mut("").unwrap();
1152 *result = Value::Integer(100);
1153 assert_eq!(v, Value::Integer(100));
1154 }
1155
1156 #[test]
1157 fn test_get_path_mut_modify() {
1158 let mut map = IndexMap::new();
1159 map.insert("key".to_string(), Value::Integer(42));
1160 let mut v = Value::Mapping(map);
1161
1162 *v.get_path_mut("key").unwrap() = Value::Integer(100);
1163 assert_eq!(v.get_path("key").unwrap().as_i64(), Some(100));
1164 }
1165
1166 #[test]
1167 fn test_get_path_mut_not_found() {
1168 let mut map = IndexMap::new();
1169 map.insert("key".to_string(), Value::Integer(42));
1170 let mut v = Value::Mapping(map);
1171 assert!(v.get_path_mut("nonexistent").is_err());
1172 }
1173
1174 #[test]
1175 fn test_get_path_mut_on_non_mapping() {
1176 let mut v = Value::Integer(42);
1177 assert!(v.get_path_mut("key").is_err());
1178 }
1179
1180 #[test]
1181 fn test_get_path_mut_array() {
1182 let mut map = IndexMap::new();
1183 map.insert(
1184 "items".to_string(),
1185 Value::Sequence(vec![Value::Integer(1), Value::Integer(2)]),
1186 );
1187 let mut v = Value::Mapping(map);
1188
1189 *v.get_path_mut("items[1]").unwrap() = Value::Integer(99);
1190 assert_eq!(v.get_path("items[1]").unwrap().as_i64(), Some(99));
1191 }
1192
1193 #[test]
1194 fn test_get_path_mut_array_out_of_bounds() {
1195 let mut map = IndexMap::new();
1196 map.insert(
1197 "items".to_string(),
1198 Value::Sequence(vec![Value::Integer(1)]),
1199 );
1200 let mut v = Value::Mapping(map);
1201 assert!(v.get_path_mut("items[99]").is_err());
1202 }
1203
1204 #[test]
1205 fn test_get_path_mut_array_on_non_sequence() {
1206 let mut map = IndexMap::new();
1207 map.insert("key".to_string(), Value::Integer(42));
1208 let mut v = Value::Mapping(map);
1209 assert!(v.get_path_mut("key[0]").is_err());
1210 }
1211
1212 #[test]
1213 fn test_set_path_empty() {
1214 let mut v = Value::Integer(42);
1215 v.set_path("", Value::Integer(100)).unwrap();
1216 assert_eq!(v, Value::Integer(100));
1217 }
1218
1219 #[test]
1220 fn test_set_path_simple() {
1221 let mut map = IndexMap::new();
1222 map.insert("key".to_string(), Value::Integer(42));
1223 let mut v = Value::Mapping(map);
1224
1225 v.set_path("key", Value::Integer(100)).unwrap();
1226 assert_eq!(v.get_path("key").unwrap().as_i64(), Some(100));
1227 }
1228
1229 #[test]
1230 fn test_set_path_new_key() {
1231 let mut map = IndexMap::new();
1232 map.insert("existing".to_string(), Value::Integer(1));
1233 let mut v = Value::Mapping(map);
1234
1235 v.set_path("new_key", Value::Integer(42)).unwrap();
1236 assert_eq!(v.get_path("new_key").unwrap().as_i64(), Some(42));
1237 }
1238
1239 #[test]
1240 fn test_set_path_creates_intermediate_mappings() {
1241 let mut v = Value::Mapping(IndexMap::new());
1242 v.set_path("a.b.c", Value::Integer(42)).unwrap();
1243 assert_eq!(v.get_path("a.b.c").unwrap().as_i64(), Some(42));
1244 }
1245
1246 #[test]
1247 fn test_set_path_array_element() {
1248 let mut map = IndexMap::new();
1249 map.insert(
1250 "items".to_string(),
1251 Value::Sequence(vec![Value::Integer(1), Value::Integer(2)]),
1252 );
1253 let mut v = Value::Mapping(map);
1254
1255 v.set_path("items[0]", Value::Integer(99)).unwrap();
1256 assert_eq!(v.get_path("items[0]").unwrap().as_i64(), Some(99));
1257 }
1258
1259 #[test]
1260 fn test_set_path_array_out_of_bounds() {
1261 let mut map = IndexMap::new();
1262 map.insert(
1263 "items".to_string(),
1264 Value::Sequence(vec![Value::Integer(1)]),
1265 );
1266 let mut v = Value::Mapping(map);
1267 assert!(v.set_path("items[99]", Value::Integer(42)).is_err());
1268 }
1269
1270 #[test]
1271 fn test_set_path_on_non_mapping() {
1272 let mut v = Value::Integer(42);
1273 assert!(v.set_path("key", Value::Integer(1)).is_err());
1274 }
1275
1276 #[test]
1277 fn test_set_path_key_on_non_mapping_intermediate() {
1278 let mut map = IndexMap::new();
1279 map.insert("key".to_string(), Value::Integer(42));
1280 let mut v = Value::Mapping(map);
1281 assert!(v.set_path("key.subkey", Value::Integer(1)).is_err());
1283 }
1284
1285 #[test]
1286 fn test_set_path_index_on_non_sequence() {
1287 let mut map = IndexMap::new();
1288 map.insert("key".to_string(), Value::Integer(42));
1289 let mut v = Value::Mapping(map);
1290 assert!(v.set_path("key[0]", Value::Integer(1)).is_err());
1291 }
1292
1293 #[test]
1294 fn test_set_path_intermediate_index_out_of_bounds() {
1295 let mut map = IndexMap::new();
1296 map.insert(
1297 "items".to_string(),
1298 Value::Sequence(vec![Value::Mapping(IndexMap::new())]),
1299 );
1300 let mut v = Value::Mapping(map);
1301 assert!(v.set_path("items[99].key", Value::Integer(1)).is_err());
1302 }
1303
1304 #[test]
1305 fn test_merged_non_mutating() {
1306 let mut base_map = IndexMap::new();
1307 base_map.insert("a".to_string(), Value::Integer(1));
1308 let base = Value::Mapping(base_map);
1309
1310 let mut overlay_map = IndexMap::new();
1311 overlay_map.insert("b".to_string(), Value::Integer(2));
1312 let overlay = Value::Mapping(overlay_map);
1313
1314 let result = base.merged(overlay);
1315
1316 assert_eq!(result.get_path("a").unwrap().as_i64(), Some(1));
1317 assert_eq!(result.get_path("b").unwrap().as_i64(), Some(2));
1318 }
1319
1320 #[test]
1321 fn test_parse_path_invalid_index() {
1322 assert!(parse_path("items[abc]").is_err());
1323 }
1324
1325 #[test]
1326 fn test_parse_path_unexpected_bracket() {
1327 assert!(parse_path("items]").is_err());
1328 }
1329
1330 #[test]
1331 fn test_is_type_negative_cases() {
1332 let integer = Value::Integer(42);
1333 assert!(!integer.is_null());
1334 assert!(!integer.is_bool());
1335 assert!(!integer.is_float());
1336 assert!(!integer.is_string());
1337 assert!(!integer.is_sequence());
1338 assert!(!integer.is_mapping());
1339 assert!(!integer.is_bytes());
1340 }
1341
1342 #[test]
1345 fn test_bytes_is_bytes() {
1346 let bytes = Value::Bytes(vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]); assert!(bytes.is_bytes());
1348 assert!(!bytes.is_string());
1349 assert!(!bytes.is_null());
1350 }
1351
1352 #[test]
1353 fn test_bytes_as_bytes() {
1354 let bytes = Value::Bytes(vec![1, 2, 3, 4, 5]);
1355 assert_eq!(bytes.as_bytes(), Some(&[1u8, 2, 3, 4, 5][..]));
1356 }
1357
1358 #[test]
1359 fn test_bytes_as_bytes_non_bytes() {
1360 assert!(Value::String("hello".into()).as_bytes().is_none());
1361 assert!(Value::Integer(42).as_bytes().is_none());
1362 }
1363
1364 #[test]
1365 fn test_bytes_type_name() {
1366 assert_eq!(Value::Bytes(vec![]).type_name(), "bytes");
1367 }
1368
1369 #[test]
1370 fn test_bytes_display() {
1371 let bytes = Value::Bytes(vec![1, 2, 3, 4, 5]);
1372 assert_eq!(format!("{}", bytes), "<bytes: 5 bytes>");
1373
1374 let empty = Value::Bytes(vec![]);
1375 assert_eq!(format!("{}", empty), "<bytes: 0 bytes>");
1376 }
1377
1378 #[test]
1379 fn test_bytes_from_vec() {
1380 let v: Value = vec![0x48u8, 0x65, 0x6c, 0x6c, 0x6f].into();
1381 assert!(v.is_bytes());
1382 assert_eq!(v.as_bytes(), Some(&[0x48u8, 0x65, 0x6c, 0x6c, 0x6f][..]));
1383 }
1384
1385 #[test]
1386 fn test_bytes_serialize_to_base64() {
1387 let bytes = Value::Bytes(vec![0x48, 0x65, 0x6c, 0x6c, 0x6f]); let yaml = serde_yaml::to_string(&bytes).unwrap();
1389 assert!(yaml.contains("SGVsbG8="));
1391 }
1392
1393 #[test]
1394 fn test_bytes_serialize_empty() {
1395 let bytes = Value::Bytes(vec![]);
1396 let json = serde_json::to_string(&bytes).unwrap();
1397 assert_eq!(json, "\"\"");
1399 }
1400
1401 #[test]
1402 fn test_bytes_equality() {
1403 let a = Value::Bytes(vec![1, 2, 3]);
1404 let b = Value::Bytes(vec![1, 2, 3]);
1405 let c = Value::Bytes(vec![1, 2, 4]);
1406
1407 assert_eq!(a, b);
1408 assert_ne!(a, c);
1409 }
1410
1411 #[test]
1412 fn test_bytes_clone() {
1413 let original = Value::Bytes(vec![1, 2, 3, 4, 5]);
1414 let cloned = original.clone();
1415 assert_eq!(original, cloned);
1416 }
1417}