1use crate::de::is_list_context;
7use crate::error::{Error, Result};
8use indexmap::IndexMap;
9use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
10use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
11use std::fmt;
12use std::ops::Index;
13
14#[derive(Debug, Clone, PartialEq)]
38pub enum Value {
39 Bool(bool),
41
42 Integer(i32),
44
45 Integer64(i64),
47
48 Float(f64),
50
51 String(String),
53
54 Array(Vec<Value>),
56
57 List(Vec<Value>),
59
60 Group(Map),
62}
63
64pub type Map = IndexMap<String, Value>;
67
68#[derive(Debug, Clone, PartialEq)]
70enum PathSegment<'a> {
71 Key(&'a str),
73 Index(usize),
75}
76
77fn parse_path(path: &str) -> Option<Vec<PathSegment<'_>>> {
86 if path.is_empty() {
87 return None;
88 }
89
90 let mut segments = Vec::new();
91 for part in path.split('.') {
92 if part.is_empty() {
93 return None;
94 }
95
96 if part.starts_with('[') && part.ends_with(']') {
97 let inner = &part[1..part.len() - 1];
98 let index: usize = inner.parse().ok()?;
99 segments.push(PathSegment::Index(index));
100 } else if let Ok(index) = part.parse::<usize>() {
101 segments.push(PathSegment::Index(index));
102 } else {
103 segments.push(PathSegment::Key(part));
104 }
105 }
106
107 if segments.is_empty() {
108 None
109 } else {
110 Some(segments)
111 }
112}
113
114impl Value {
115 pub fn is_bool(&self) -> bool {
117 matches!(self, Value::Bool(_))
118 }
119
120 pub fn is_integer(&self) -> bool {
122 matches!(self, Value::Integer(_) | Value::Integer64(_))
123 }
124
125 pub fn is_i32(&self) -> bool {
127 matches!(self, Value::Integer(_))
128 }
129
130 pub fn is_i64(&self) -> bool {
132 matches!(self, Value::Integer64(_))
133 }
134
135 pub fn is_float(&self) -> bool {
137 matches!(self, Value::Float(_))
138 }
139
140 pub fn is_number(&self) -> bool {
142 matches!(
143 self,
144 Value::Integer(_) | Value::Integer64(_) | Value::Float(_)
145 )
146 }
147
148 pub fn is_string(&self) -> bool {
150 matches!(self, Value::String(_))
151 }
152
153 pub fn is_array(&self) -> bool {
155 matches!(self, Value::Array(_))
156 }
157
158 pub fn is_list(&self) -> bool {
160 matches!(self, Value::List(_))
161 }
162
163 pub fn is_group(&self) -> bool {
165 matches!(self, Value::Group(_))
166 }
167
168 pub fn as_bool(&self) -> Option<bool> {
170 match self {
171 Value::Bool(b) => Some(*b),
172 _ => None,
173 }
174 }
175
176 pub fn as_i32(&self) -> Option<i32> {
178 match self {
179 Value::Integer(i) => Some(*i),
180 Value::Integer64(i) if *i >= i32::MIN as i64 && *i <= i32::MAX as i64 => {
181 Some(*i as i32)
182 }
183 _ => None,
184 }
185 }
186
187 pub fn as_i64(&self) -> Option<i64> {
189 match self {
190 Value::Integer(i) => Some(*i as i64),
191 Value::Integer64(i) => Some(*i),
192 _ => None,
193 }
194 }
195
196 pub fn as_f64(&self) -> Option<f64> {
198 match self {
199 Value::Float(f) => Some(*f),
200 Value::Integer(i) => Some(*i as f64),
201 Value::Integer64(i) => Some(*i as f64),
202 _ => None,
203 }
204 }
205
206 pub fn as_str(&self) -> Option<&str> {
208 match self {
209 Value::String(s) => Some(s),
210 _ => None,
211 }
212 }
213
214 pub fn as_array(&self) -> Option<&Vec<Value>> {
216 match self {
217 Value::Array(arr) | Value::List(arr) => Some(arr),
218 _ => None,
219 }
220 }
221
222 pub fn as_group(&self) -> Option<&Map> {
224 match self {
225 Value::Group(map) => Some(map),
226 _ => None,
227 }
228 }
229
230 pub fn get<S: AsRef<str>>(&self, key: S) -> Option<&Value> {
234 match self {
235 Value::Group(map) => map.get(key.as_ref()),
236 _ => None,
237 }
238 }
239
240 pub fn get_mut<S: AsRef<str>>(&mut self, key: S) -> Option<&mut Value> {
244 match self {
245 Value::Group(map) => map.get_mut(key.as_ref()),
246 _ => None,
247 }
248 }
249
250 pub fn get_index(&self, index: usize) -> Option<&Value> {
254 match self {
255 Value::Array(arr) | Value::List(arr) => arr.get(index),
256 _ => None,
257 }
258 }
259
260 pub fn lookup(&self, path: &str) -> Option<&Value> {
283 let segments = parse_path(path)?;
284 let mut current = self;
285 for segment in &segments {
286 match segment {
287 PathSegment::Key(key) => current = current.get(*key)?,
288 PathSegment::Index(index) => current = current.get_index(*index)?,
289 }
290 }
291 Some(current)
292 }
293
294 pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
315 let segments = parse_path(path)?;
316 let mut current = self;
317 for segment in &segments {
318 match segment {
319 PathSegment::Key(key) => match current {
320 Value::Group(map) => current = map.get_mut(*key)?,
321 _ => return None,
322 },
323 PathSegment::Index(index) => match current {
324 Value::Array(arr) | Value::List(arr) => current = arr.get_mut(*index)?,
325 _ => return None,
326 },
327 }
328 }
329 Some(current)
330 }
331
332 pub fn set(&mut self, path: &str, value: Value) -> Option<()> {
350 let segments = parse_path(path)?;
351 if segments.is_empty() {
352 return None;
353 }
354
355 let mut current = self;
356
357 for segment in &segments[..segments.len() - 1] {
359 match segment {
360 PathSegment::Key(key) => match current {
361 Value::Group(map) => {
362 current = map
363 .entry(key.to_string())
364 .or_insert_with(|| Value::Group(IndexMap::new()));
365 }
366 _ => return None,
367 },
368 PathSegment::Index(index) => match current {
369 Value::Array(arr) | Value::List(arr) => {
370 current = arr.get_mut(*index)?;
371 }
372 _ => return None,
373 },
374 }
375 }
376
377 match segments.last().unwrap() {
379 PathSegment::Key(key) => match current {
380 Value::Group(map) => {
381 map.insert(key.to_string(), value);
382 Some(())
383 }
384 _ => None,
385 },
386 PathSegment::Index(index) => match current {
387 Value::Array(arr) | Value::List(arr) => {
388 if *index < arr.len() {
389 arr[*index] = value;
390 Some(())
391 } else {
392 None
393 }
394 }
395 _ => None,
396 },
397 }
398 }
399
400 pub fn remove(&mut self, path: &str) -> Option<Value> {
418 let segments = parse_path(path)?;
419 if segments.is_empty() {
420 return None;
421 }
422
423 let mut current = self;
424
425 for segment in &segments[..segments.len() - 1] {
427 match segment {
428 PathSegment::Key(key) => match current {
429 Value::Group(map) => current = map.get_mut(*key)?,
430 _ => return None,
431 },
432 PathSegment::Index(index) => match current {
433 Value::Array(arr) | Value::List(arr) => current = arr.get_mut(*index)?,
434 _ => return None,
435 },
436 }
437 }
438
439 match segments.last().unwrap() {
441 PathSegment::Key(key) => match current {
442 Value::Group(map) => map.shift_remove(*key),
443 _ => None,
444 },
445 PathSegment::Index(index) => match current {
446 Value::Array(arr) | Value::List(arr) => {
447 if *index < arr.len() {
448 Some(arr.remove(*index))
449 } else {
450 None
451 }
452 }
453 _ => None,
454 },
455 }
456 }
457
458 pub fn from_str(s: &str) -> Result<Value> {
470 crate::from_str(s)
471 }
472
473 pub fn to_string(&self) -> Result<String> {
487 crate::to_string(self)
488 }
489}
490
491impl Index<&str> for Value {
494 type Output = Value;
495
496 fn index(&self, key: &str) -> &Self::Output {
497 self.lookup(key).expect("key not found in group")
498 }
499}
500
501impl Index<usize> for Value {
502 type Output = Value;
503
504 fn index(&self, index: usize) -> &Self::Output {
505 self.get_index(index).expect("index out of bounds")
506 }
507}
508
509impl PartialEq<bool> for Value {
511 fn eq(&self, other: &bool) -> bool {
512 self.as_bool() == Some(*other)
513 }
514}
515
516impl PartialEq<i32> for Value {
517 fn eq(&self, other: &i32) -> bool {
518 self.as_i32() == Some(*other)
519 }
520}
521
522impl PartialEq<i64> for Value {
523 fn eq(&self, other: &i64) -> bool {
524 self.as_i64() == Some(*other)
525 }
526}
527
528impl PartialEq<f64> for Value {
529 fn eq(&self, other: &f64) -> bool {
530 self.as_f64() == Some(*other)
531 }
532}
533
534impl PartialEq<str> for Value {
535 fn eq(&self, other: &str) -> bool {
536 self.as_str() == Some(other)
537 }
538}
539
540impl PartialEq<&str> for Value {
541 fn eq(&self, other: &&str) -> bool {
542 self.as_str() == Some(*other)
543 }
544}
545
546impl PartialEq<String> for Value {
547 fn eq(&self, other: &String) -> bool {
548 self.as_str() == Some(other.as_str())
549 }
550}
551
552impl fmt::Display for Value {
554 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
555 match self {
556 Value::Bool(b) => write!(f, "{}", b),
557 Value::Integer(i) => write!(f, "{}", i),
558 Value::Integer64(i) => write!(f, "{}L", i),
559 Value::Float(fl) => write!(f, "{}", fl),
560 Value::String(s) => write!(f, "\"{}\"", s),
561 Value::Array(arr) => {
562 write!(f, "[")?;
563 for (i, v) in arr.iter().enumerate() {
564 if i > 0 {
565 write!(f, ", ")?;
566 }
567 write!(f, "{}", v)?;
568 }
569 write!(f, "]")
570 }
571 Value::List(arr) => {
572 write!(f, "(")?;
573 for (i, v) in arr.iter().enumerate() {
574 if i > 0 {
575 write!(f, ", ")?;
576 }
577 write!(f, "{}", v)?;
578 }
579 write!(f, ")")
580 }
581 Value::Group(map) => {
582 write!(f, "{{")?;
583 for (i, (k, v)) in map.iter().enumerate() {
584 if i > 0 {
585 write!(f, ", ")?;
586 }
587 write!(f, "{}: {}", k, v)?;
588 }
589 write!(f, "}}")
590 }
591 }
592 }
593}
594
595impl Serialize for Value {
597 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
598 where
599 S: Serializer,
600 {
601 match self {
602 Value::Bool(b) => serializer.serialize_bool(*b),
603 Value::Integer(i) => serializer.serialize_i32(*i),
604 Value::Integer64(i) => serializer.serialize_i64(*i),
605 Value::Float(f) => serializer.serialize_f64(*f),
606 Value::String(s) => serializer.serialize_str(s),
607 Value::Array(arr) => {
608 let mut seq = serializer.serialize_seq(Some(arr.len()))?;
609 for element in arr {
610 seq.serialize_element(element)?;
611 }
612 seq.end()
613 }
614 Value::List(arr) => {
615 use serde::ser::SerializeTuple;
616 let mut tup = serializer.serialize_tuple(arr.len())?;
617 for element in arr {
618 tup.serialize_element(element)?;
619 }
620 tup.end()
621 }
622 Value::Group(map) => {
623 let mut map_ser = serializer.serialize_map(Some(map.len()))?;
624 for (k, v) in map {
625 map_ser.serialize_entry(k, v)?;
626 }
627 map_ser.end()
628 }
629 }
630 }
631}
632
633impl<'de> Deserialize<'de> for Value {
635 fn deserialize<D>(deserializer: D) -> std::result::Result<Value, D::Error>
636 where
637 D: Deserializer<'de>,
638 {
639 deserializer.deserialize_any(ValueVisitor)
640 }
641}
642
643struct ValueVisitor;
644
645impl<'de> Visitor<'de> for ValueVisitor {
646 type Value = Value;
647
648 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
649 formatter.write_str("any valid libconfig value")
650 }
651
652 fn visit_bool<E>(self, value: bool) -> std::result::Result<Value, E>
653 where
654 E: de::Error,
655 {
656 Ok(Value::Bool(value))
657 }
658
659 fn visit_i8<E>(self, value: i8) -> std::result::Result<Value, E>
660 where
661 E: de::Error,
662 {
663 Ok(Value::Integer(value as i32))
664 }
665
666 fn visit_i16<E>(self, value: i16) -> std::result::Result<Value, E>
667 where
668 E: de::Error,
669 {
670 Ok(Value::Integer(value as i32))
671 }
672
673 fn visit_i32<E>(self, value: i32) -> std::result::Result<Value, E>
674 where
675 E: de::Error,
676 {
677 Ok(Value::Integer(value))
678 }
679
680 fn visit_i64<E>(self, value: i64) -> std::result::Result<Value, E>
681 where
682 E: de::Error,
683 {
684 Ok(Value::Integer64(value))
685 }
686
687 fn visit_u8<E>(self, value: u8) -> std::result::Result<Value, E>
688 where
689 E: de::Error,
690 {
691 Ok(Value::Integer(value as i32))
692 }
693
694 fn visit_u16<E>(self, value: u16) -> std::result::Result<Value, E>
695 where
696 E: de::Error,
697 {
698 Ok(Value::Integer(value as i32))
699 }
700
701 fn visit_u32<E>(self, value: u32) -> std::result::Result<Value, E>
702 where
703 E: de::Error,
704 {
705 if value <= i32::MAX as u32 {
706 Ok(Value::Integer(value as i32))
707 } else {
708 Ok(Value::Integer64(value as i64))
709 }
710 }
711
712 fn visit_u64<E>(self, value: u64) -> std::result::Result<Value, E>
713 where
714 E: de::Error,
715 {
716 if value <= i32::MAX as u64 {
717 Ok(Value::Integer(value as i32))
718 } else {
719 Ok(Value::Integer64(value as i64))
720 }
721 }
722
723 fn visit_f32<E>(self, value: f32) -> std::result::Result<Value, E>
724 where
725 E: de::Error,
726 {
727 Ok(Value::Float(value as f64))
728 }
729
730 fn visit_f64<E>(self, value: f64) -> std::result::Result<Value, E>
731 where
732 E: de::Error,
733 {
734 Ok(Value::Float(value))
735 }
736
737 fn visit_str<E>(self, value: &str) -> std::result::Result<Value, E>
738 where
739 E: de::Error,
740 {
741 Ok(Value::String(value.to_string()))
742 }
743
744 fn visit_borrowed_str<E>(self, value: &'de str) -> std::result::Result<Value, E>
745 where
746 E: de::Error,
747 {
748 Ok(Value::String(value.to_string()))
749 }
750
751 fn visit_string<E>(self, value: String) -> std::result::Result<Value, E>
752 where
753 E: de::Error,
754 {
755 Ok(Value::String(value))
756 }
757
758 fn visit_seq<A>(self, mut seq: A) -> std::result::Result<Value, A::Error>
759 where
760 A: SeqAccess<'de>,
761 {
762 let is_list = is_list_context();
763 let mut values = Vec::new();
764 while let Some(value) = seq.next_element()? {
765 values.push(value);
766 }
767 if is_list {
768 Ok(Value::List(values))
769 } else {
770 Ok(Value::Array(values))
771 }
772 }
773
774 fn visit_map<A>(self, mut map: A) -> std::result::Result<Value, A::Error>
775 where
776 A: MapAccess<'de>,
777 {
778 let mut values = Map::new();
779 while let Some((key, value)) = map.next_entry()? {
780 values.insert(key, value);
781 }
782 Ok(Value::Group(values))
783 }
784}
785
786pub fn from_value<T>(value: Value) -> Result<T>
798where
799 T: de::DeserializeOwned,
800{
801 T::deserialize(value).map_err(|e| Error::Message(format!("failed to deserialize: {}", e)))
802}
803
804fn to_string_format_impl(value: &Value, indent_level: usize, is_nested: bool) -> Result<String> {
806 const INDENT_SIZE: usize = 2;
807
808 match value {
809 Value::Bool(b) => Ok(if *b {
810 "true".to_string()
811 } else {
812 "false".to_string()
813 }),
814 Value::Integer(i) => Ok(i.to_string()),
815 Value::Integer64(i) => Ok(format!("{}L", i)),
816 Value::Float(f) => {
817 let s = f.to_string();
818 if !s.contains('.') && !s.contains('e') && !s.contains('E') {
819 Ok(format!("{}.0", s))
820 } else {
821 Ok(s)
822 }
823 }
824 Value::String(s) => {
825 let mut result = String::from("\"");
826 for ch in s.chars() {
827 match ch {
828 '"' => result.push_str("\\\""),
829 '\\' => result.push_str("\\\\"),
830 '\n' => result.push_str("\\n"),
831 '\r' => result.push_str("\\r"),
832 '\t' => result.push_str("\\t"),
833 '\x0C' => result.push_str("\\f"),
834 '\x08' => result.push_str("\\b"),
835 '\x0B' => result.push_str("\\v"),
836 '\x07' => result.push_str("\\a"),
837 _ => result.push(ch),
838 }
839 }
840 result.push('"');
841 Ok(result)
842 }
843 Value::Array(arr) => {
844 let mut result = String::from("[");
845 for (i, elem) in arr.iter().enumerate() {
846 if i > 0 {
847 result.push_str(", ");
848 }
849 result.push_str(&to_string_format_impl(elem, indent_level, true)?);
850 }
851 result.push(']');
852 Ok(result)
853 }
854 Value::List(arr) => {
855 let mut result = String::from("(");
856 for (i, elem) in arr.iter().enumerate() {
857 if i > 0 {
858 result.push_str(", ");
859 }
860 result.push_str(&to_string_format_impl(elem, indent_level, true)?);
861 }
862 result.push(')');
863 Ok(result)
864 }
865 Value::Group(map) => {
866 if !is_nested {
867 let mut output = String::new();
868 let mut first = true;
869 for (key, val) in map {
870 if !first {
871 output.push(';');
872 output.push('\n');
873 }
874 first = false;
875 output.push_str(key);
876 output.push_str(" = ");
877 let val_str = to_string_format_impl(val, indent_level, true)?;
878 output.push_str(&val_str);
879 }
880 if !output.is_empty() {
881 output.push(';');
882 }
883 Ok(output)
884 } else {
885 let mut output = String::from("{");
887 let next_indent = indent_level + 1;
888 let indent_str = " ".repeat(next_indent * INDENT_SIZE);
889
890 let mut first = true;
891 for (key, val) in map {
892 if !first {
893 output.push(';');
894 }
895 output.push('\n');
896 output.push_str(&indent_str);
897 first = false;
898
899 output.push_str(key);
900 output.push_str(" = ");
901 let val_str = to_string_format_impl(val, next_indent, true)?;
902 output.push_str(&val_str);
903 }
904
905 if !map.is_empty() {
906 output.push(';');
907 }
908 output.push('\n');
909 output.push_str(&" ".repeat(indent_level * INDENT_SIZE));
910 output.push('}');
911 Ok(output)
912 }
913 }
914 }
915}
916
917impl<'de> Deserializer<'de> for Value {
919 type Error = Error;
920
921 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
922 where
923 V: Visitor<'de>,
924 {
925 match self {
926 Value::Bool(b) => visitor.visit_bool(b),
927 Value::Integer(i) => visitor.visit_i32(i),
928 Value::Integer64(i) => visitor.visit_i64(i),
929 Value::Float(f) => visitor.visit_f64(f),
930 Value::String(s) => visitor.visit_string(s),
931 Value::Array(arr) | Value::List(arr) => {
932 visitor.visit_seq(SeqDeserializer::new(arr.into_iter()))
933 }
934 Value::Group(map) => visitor.visit_map(MapDeserializer::new(map.into_iter())),
935 }
936 }
937
938 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
939 where
940 V: Visitor<'de>,
941 {
942 visitor.visit_some(self)
943 }
944
945 serde::forward_to_deserialize_any! {
946 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
947 bytes byte_buf unit unit_struct newtype_struct seq tuple
948 tuple_struct map struct enum identifier ignored_any
949 }
950}
951
952struct SeqDeserializer {
953 iter: std::vec::IntoIter<Value>,
954}
955
956impl SeqDeserializer {
957 fn new(iter: std::vec::IntoIter<Value>) -> Self {
958 SeqDeserializer { iter }
959 }
960}
961
962impl<'de> SeqAccess<'de> for SeqDeserializer {
963 type Error = Error;
964
965 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
966 where
967 T: de::DeserializeSeed<'de>,
968 {
969 match self.iter.next() {
970 Some(value) => seed.deserialize(value).map(Some),
971 None => Ok(None),
972 }
973 }
974}
975
976struct MapDeserializer {
977 iter: indexmap::map::IntoIter<String, Value>,
978 value: Option<Value>,
979}
980
981impl MapDeserializer {
982 fn new(iter: indexmap::map::IntoIter<String, Value>) -> Self {
983 MapDeserializer { iter, value: None }
984 }
985}
986
987impl<'de> MapAccess<'de> for MapDeserializer {
988 type Error = Error;
989
990 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
991 where
992 K: de::DeserializeSeed<'de>,
993 {
994 match self.iter.next() {
995 Some((key, value)) => {
996 self.value = Some(value);
997 seed.deserialize(Value::String(key)).map(Some)
998 }
999 None => Ok(None),
1000 }
1001 }
1002
1003 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
1004 where
1005 V: de::DeserializeSeed<'de>,
1006 {
1007 match self.value.take() {
1008 Some(value) => seed.deserialize(value),
1009 None => Err(Error::Message("value is missing".to_string())),
1010 }
1011 }
1012}
1013
1014#[derive(Debug, Clone, PartialEq)]
1041pub struct Config {
1042 pub value: Value,
1044 pub explicit_braces: bool,
1046}
1047
1048impl Config {
1049 pub fn new() -> Self {
1051 Config {
1052 value: Value::Group(Map::new()),
1053 explicit_braces: false,
1054 }
1055 }
1056
1057 pub fn from_str(s: &str) -> Result<Config> {
1077 let trimmed = s.trim_start();
1078 let explicit_braces = trimmed.starts_with('{');
1079 let value: Value = crate::from_str(s)?;
1080 Ok(Config {
1081 value,
1082 explicit_braces,
1083 })
1084 }
1085
1086 pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Config> {
1098 let contents = std::fs::read_to_string(path)
1099 .map_err(|e| Error::Message(format!("failed to read file: {}", e)))?;
1100 Config::from_str(&contents)
1101 }
1102
1103 pub fn to_string(&self) -> Result<String> {
1106 to_string_format_impl(&self.value, 0, self.explicit_braces)
1107 }
1108}
1109
1110impl Default for Config {
1111 fn default() -> Self {
1112 Config::new()
1113 }
1114}
1115
1116impl From<Value> for Config {
1117 fn from(value: Value) -> Self {
1118 Config {
1119 value,
1120 explicit_braces: false,
1121 }
1122 }
1123}
1124
1125impl std::ops::Deref for Config {
1126 type Target = Value;
1127
1128 fn deref(&self) -> &Value {
1129 &self.value
1130 }
1131}
1132
1133impl std::ops::DerefMut for Config {
1134 fn deref_mut(&mut self) -> &mut Value {
1135 &mut self.value
1136 }
1137}
1138
1139impl fmt::Display for Config {
1140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1141 match self.to_string() {
1142 Ok(s) => write!(f, "{}", s),
1143 Err(e) => write!(f, "<error: {}>", e),
1144 }
1145 }
1146}
1147
1148impl Serialize for Config {
1149 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1150 where
1151 S: Serializer,
1152 {
1153 self.value.serialize(serializer)
1154 }
1155}
1156
1157#[cfg(test)]
1158mod tests {
1159 use super::*;
1160 use crate::from_str;
1161
1162 #[test]
1163 fn test_value_types() {
1164 let v = Value::Bool(true);
1165 assert!(v.is_bool());
1166 assert_eq!(v.as_bool(), Some(true));
1167
1168 let v = Value::Integer(42);
1169 assert!(v.is_i32());
1170 assert_eq!(v.as_i32(), Some(42));
1171
1172 let v = Value::Float(3.14);
1173 assert!(v.is_float());
1174 assert_eq!(v.as_f64(), Some(3.14));
1175
1176 let v = Value::String("hello".to_string());
1177 assert!(v.is_string());
1178 assert_eq!(v.as_str(), Some("hello"));
1179 }
1180
1181 #[test]
1182 fn test_value_indexing() {
1183 let config = r#"
1184 {
1185 name = "Test";
1186 count = 42;
1187 items = [1, 2, 3];
1188 }
1189 "#;
1190
1191 let v: Value = from_str(config).unwrap();
1192 assert_eq!(v["name"], "Test");
1193 assert_eq!(v["count"], 42);
1194 assert_eq!(v["items"][0], 1);
1195 assert_eq!(v["items"][1], 2);
1196 }
1197
1198 #[test]
1199 fn test_value_lookup() {
1200 let config = r#"
1201 {
1202 application = {
1203 window = {
1204 title = "My App";
1205 size = { w = 640; h = 480; };
1206 };
1207 };
1208 }
1209 "#;
1210
1211 let v: Value = from_str(config).unwrap();
1212 assert_eq!(
1213 v.lookup("application.window.title")
1214 .and_then(|v| v.as_str()),
1215 Some("My App")
1216 );
1217 assert_eq!(
1218 v.lookup("application.window.size")
1219 .and_then(|v| v.get("w"))
1220 .and_then(|v| v.as_i32()),
1221 Some(640)
1222 );
1223 }
1224
1225 #[test]
1226 fn test_value_lookup_with_array_index() {
1227 let config = r#"
1228 {
1229 name = "Test";
1230 items = [10, 20, 30];
1231 nested = {
1232 ports = [80, 443];
1233 };
1234 }
1235 "#;
1236
1237 let v: Value = from_str(config).unwrap();
1238
1239 assert_eq!(v.lookup("items.0").and_then(|v| v.as_i32()), Some(10));
1241 assert_eq!(v.lookup("items.1").and_then(|v| v.as_i32()), Some(20));
1242 assert_eq!(v.lookup("items.2").and_then(|v| v.as_i32()), Some(30));
1243
1244 assert_eq!(
1246 v.lookup("nested.ports.0").and_then(|v| v.as_i32()),
1247 Some(80)
1248 );
1249 assert_eq!(
1250 v.lookup("nested.ports.1").and_then(|v| v.as_i32()),
1251 Some(443)
1252 );
1253
1254 assert!(v.lookup("items.5").is_none());
1256
1257 assert!(v.lookup("name.0").is_none());
1259
1260 assert_eq!(v["items.0"], 10);
1262 assert_eq!(v["nested.ports.1"], 443);
1263 }
1264
1265 #[test]
1266 fn test_value_comparison() {
1267 let v = Value::Bool(true);
1268 assert!(v == true);
1269
1270 let v = Value::Integer(42);
1271 assert!(v == 42);
1272
1273 let v = Value::String("hello".to_string());
1274 assert!(v == "hello");
1275 }
1276
1277 #[test]
1278 fn test_value_round_trip() {
1279 let config = r#"
1280 {
1281 name = "Test";
1282 version = 1;
1283 enabled = true;
1284 pi = 3.14;
1285 items = [1, 2, 3];
1286 }
1287 "#;
1288
1289 let v: Value = from_str(config).unwrap();
1290 let serialized = crate::to_string(&v).unwrap();
1291 let v2: Value = from_str(&serialized).unwrap();
1292
1293 assert_eq!(v["name"], v2["name"]);
1294 assert_eq!(v["version"], v2["version"]);
1295 assert_eq!(v["enabled"], v2["enabled"]);
1296 }
1297
1298 #[test]
1301 fn test_parse_path_dotted_keys() {
1302 let segs = parse_path("a.b.c").unwrap();
1303 assert_eq!(
1304 segs,
1305 vec![
1306 PathSegment::Key("a"),
1307 PathSegment::Key("b"),
1308 PathSegment::Key("c"),
1309 ]
1310 );
1311 }
1312
1313 #[test]
1314 fn test_parse_path_bracket_index() {
1315 let segs = parse_path("items.[0].title").unwrap();
1316 assert_eq!(
1317 segs,
1318 vec![
1319 PathSegment::Key("items"),
1320 PathSegment::Index(0),
1321 PathSegment::Key("title"),
1322 ]
1323 );
1324 }
1325
1326 #[test]
1327 fn test_parse_path_bare_numeric() {
1328 let segs = parse_path("items.0").unwrap();
1329 assert_eq!(segs, vec![PathSegment::Key("items"), PathSegment::Index(0)]);
1330 }
1331
1332 #[test]
1333 fn test_parse_path_single_segment() {
1334 assert_eq!(
1335 parse_path("version").unwrap(),
1336 vec![PathSegment::Key("version")]
1337 );
1338 }
1339
1340 #[test]
1341 fn test_parse_path_invalid() {
1342 assert!(parse_path("").is_none());
1343 assert!(parse_path("a..b").is_none());
1344 assert!(parse_path(".a").is_none());
1345 assert!(parse_path("a.").is_none());
1346 assert!(parse_path("items.[abc]").is_none());
1347 assert!(parse_path("items.[-1]").is_none());
1348 assert!(parse_path("items.[]").is_none());
1349 }
1350
1351 #[test]
1354 fn test_lookup_bracket_notation() {
1355 let config = r#"
1356 {
1357 books = (
1358 { title = "Treasure Island"; price = 29; },
1359 { title = "Snow Crash"; price = 9; }
1360 );
1361 }
1362 "#;
1363 let v: Value = from_str(config).unwrap();
1364
1365 assert_eq!(
1367 v.lookup("books.[0].title").and_then(|v| v.as_str()),
1368 Some("Treasure Island")
1369 );
1370 assert_eq!(
1371 v.lookup("books.[1].price").and_then(|v| v.as_i32()),
1372 Some(9)
1373 );
1374
1375 assert_eq!(
1377 v.lookup("books.0.title").and_then(|v| v.as_str()),
1378 Some("Treasure Island")
1379 );
1380 }
1381
1382 #[test]
1383 fn test_lookup_mut_bracket_notation() {
1384 let config = r#"{ items = [10, 20, 30]; }"#;
1385 let mut v: Value = from_str(config).unwrap();
1386
1387 *v.lookup_mut("items.[1]").unwrap() = Value::Integer(99);
1388 assert_eq!(v.lookup("items.[1]").unwrap().as_i32(), Some(99));
1389 assert_eq!(v.lookup("items.1").unwrap().as_i32(), Some(99));
1390 }
1391
1392 #[test]
1395 fn test_set_existing_key() {
1396 let mut v: Value = from_str(r#"{ name = "old"; }"#).unwrap();
1397 assert_eq!(v.set("name", Value::String("new".to_string())), Some(()));
1398 assert_eq!(v.lookup("name").unwrap().as_str(), Some("new"));
1399 }
1400
1401 #[test]
1402 fn test_set_new_key() {
1403 let mut v: Value = from_str(r#"{ a = 1; }"#).unwrap();
1404 assert_eq!(v.set("b", Value::Integer(2)), Some(()));
1405 assert_eq!(v.lookup("b").unwrap().as_i32(), Some(2));
1406 }
1407
1408 #[test]
1409 fn test_set_creates_intermediate_groups() {
1410 let mut v = Value::Group(IndexMap::new());
1411 assert_eq!(v.set("a.b.c", Value::Integer(42)), Some(()));
1412 assert_eq!(v.lookup("a.b.c").unwrap().as_i32(), Some(42));
1413 assert!(v.lookup("a").unwrap().is_group());
1414 assert!(v.lookup("a.b").unwrap().is_group());
1415 }
1416
1417 #[test]
1418 fn test_set_array_element() {
1419 let mut v: Value = from_str(r#"{ items = [1, 2, 3]; }"#).unwrap();
1420 assert_eq!(v.set("items.[0]", Value::Integer(99)), Some(()));
1421 assert_eq!(v.lookup("items.[0]").unwrap().as_i32(), Some(99));
1422 }
1423
1424 #[test]
1425 fn test_set_array_out_of_bounds() {
1426 let mut v: Value = from_str(r#"{ items = [1, 2]; }"#).unwrap();
1427 assert_eq!(v.set("items.[5]", Value::Integer(99)), None);
1428 }
1429
1430 #[test]
1431 fn test_set_on_scalar_fails() {
1432 let mut v: Value = from_str(r#"{ name = "hello"; }"#).unwrap();
1433 assert_eq!(v.set("name.child", Value::Integer(1)), None);
1434 }
1435
1436 #[test]
1437 fn test_set_deeply_nested() {
1438 let mut v = Value::Group(IndexMap::new());
1439 assert_eq!(
1440 v.set("level1.level2.level3.level4", Value::Bool(true)),
1441 Some(())
1442 );
1443 assert_eq!(
1444 v.lookup("level1.level2.level3.level4").unwrap().as_bool(),
1445 Some(true)
1446 );
1447 }
1448
1449 #[test]
1450 fn test_set_into_list_element_group() {
1451 let config = r#"
1452 {
1453 books = (
1454 { title = "Old Title"; }
1455 );
1456 }
1457 "#;
1458 let mut v: Value = from_str(config).unwrap();
1459 assert_eq!(
1460 v.set("books.[0].title", Value::String("New Title".to_string())),
1461 Some(())
1462 );
1463 assert_eq!(
1464 v.lookup("books.[0].title").unwrap().as_str(),
1465 Some("New Title")
1466 );
1467 }
1468
1469 #[test]
1472 fn test_remove_group_key() {
1473 let mut v: Value = from_str(r#"{ a = 1; b = 2; c = 3; }"#).unwrap();
1474 let removed = v.remove("b");
1475 assert_eq!(removed, Some(Value::Integer(2)));
1476 assert!(v.lookup("b").is_none());
1477 assert_eq!(v.lookup("a").unwrap().as_i32(), Some(1));
1478 assert_eq!(v.lookup("c").unwrap().as_i32(), Some(3));
1479 }
1480
1481 #[test]
1482 fn test_remove_array_element() {
1483 let mut v: Value = from_str(r#"{ items = [10, 20, 30]; }"#).unwrap();
1484 let removed = v.remove("items.[1]");
1485 assert_eq!(removed, Some(Value::Integer(20)));
1486 assert_eq!(v.lookup("items.[0]").unwrap().as_i32(), Some(10));
1488 assert_eq!(v.lookup("items.[1]").unwrap().as_i32(), Some(30));
1489 assert!(v.lookup("items.[2]").is_none());
1490 }
1491
1492 #[test]
1493 fn test_remove_nested() {
1494 let config = r#"
1495 {
1496 database = {
1497 host = "localhost";
1498 port = 5432;
1499 };
1500 }
1501 "#;
1502 let mut v: Value = from_str(config).unwrap();
1503 let removed = v.remove("database.host");
1504 assert_eq!(removed, Some(Value::String("localhost".to_string())));
1505 assert!(v.lookup("database.host").is_none());
1506 assert_eq!(v.lookup("database.port").unwrap().as_i32(), Some(5432));
1507 }
1508
1509 #[test]
1510 fn test_remove_nonexistent() {
1511 let mut v: Value = from_str(r#"{ a = 1; }"#).unwrap();
1512 assert_eq!(v.remove("z"), None);
1513 assert_eq!(v.remove("a.b"), None);
1514 }
1515
1516 #[test]
1517 fn test_remove_index_out_of_bounds() {
1518 let mut v: Value = from_str(r#"{ items = [1, 2]; }"#).unwrap();
1519 assert_eq!(v.remove("items.[5]"), None);
1520 }
1521
1522 #[test]
1523 fn test_remove_entire_subtree() {
1524 let config = r#"
1525 {
1526 app = {
1527 window = { title = "hi"; };
1528 debug = false;
1529 };
1530 }
1531 "#;
1532 let mut v: Value = from_str(config).unwrap();
1533 let removed = v.remove("app.window");
1534 assert!(removed.unwrap().is_group());
1535 assert!(v.lookup("app.window").is_none());
1536 assert_eq!(v.lookup("app.debug").unwrap().as_bool(), Some(false));
1537 }
1538
1539 #[test]
1540 fn test_remove_bare_numeric_index() {
1541 let mut v: Value = from_str(r#"{ items = [10, 20, 30]; }"#).unwrap();
1542 let removed = v.remove("items.0");
1543 assert_eq!(removed, Some(Value::Integer(10)));
1544 assert_eq!(v.lookup("items.0").unwrap().as_i32(), Some(20));
1545 }
1546
1547 #[test]
1550 fn test_ordering_preserved_in_round_trip() {
1551 let input = r#"{
1552 first = 1;
1553 second = 2;
1554 third = 3;
1555 fourth = 4;
1556}"#;
1557 let v: Value = from_str(input).unwrap();
1558 let output = Config::from(v.clone()).to_string().unwrap();
1559
1560 let v_output: Value = from_str(&output).unwrap();
1562 if let Value::Group(map) = v {
1563 if let Value::Group(map_output) = v_output {
1564 let keys1: Vec<&String> = map.keys().collect();
1565 let keys2: Vec<&String> = map_output.keys().collect();
1566 assert_eq!(keys1, keys2);
1567 assert_eq!(keys1, vec!["first", "second", "third", "fourth"]);
1568 }
1569 }
1570 }
1571
1572 #[test]
1573 fn test_config_implicit_no_outer_braces() {
1574 let input = "a = 1;\nb = 2;\nc = 3;";
1575 let v: Value = from_str(input).unwrap();
1576
1577 let output = Config::from(v).to_string().unwrap();
1578
1579 assert!(!output.trim_start().starts_with('{'));
1581 assert!(!output.trim_end().ends_with('}'));
1582
1583 assert!(output.contains("a = 1"));
1585 assert!(output.contains("b = 2"));
1586 assert!(output.contains("c = 3"));
1587 }
1588
1589 #[test]
1590 fn test_config_explicit_outer_braces() {
1591 let input = "a = 1;\nb = 2;\nc = 3;";
1592 let v: Value = from_str(input).unwrap();
1593
1594 let mut config = Config::from(v);
1595 config.explicit_braces = true;
1596 let output = config.to_string().unwrap();
1597
1598 assert!(output.trim_start().starts_with('{'));
1600 assert!(output.trim_end().ends_with('}'));
1601
1602 assert!(output.contains("a = 1"));
1604 assert!(output.contains("b = 2"));
1605 assert!(output.contains("c = 3"));
1606 }
1607
1608 #[test]
1609 fn test_config_implicit_vs_explicit() {
1610 let input = "{\n a = 1;\n b = 2;\n c = 3;\n}";
1611 let v: Value = from_str(input).unwrap();
1612
1613 let output = Config::from(v.clone()).to_string().unwrap();
1615 assert!(!output.trim_start().starts_with('{'));
1616 assert!(!output.trim_end().ends_with('}'));
1617
1618 let mut config = Config::from(v);
1620 config.explicit_braces = true;
1621 let output_braces = config.to_string().unwrap();
1622 assert!(output_braces.trim_start().starts_with('{'));
1623 assert!(output_braces.trim_end().ends_with('}'));
1624 }
1625
1626 #[test]
1627 fn test_nested_groups_have_braces() {
1628 let input = r#"{
1629 outer = 1;
1630 nested = {
1631 inner = 2;
1632 };
1633}"#;
1634 let v: Value = from_str(input).unwrap();
1635 let output = Config::from(v).to_string().unwrap();
1636
1637 assert!(!output.trim_start().starts_with('{'));
1639
1640 assert!(output.contains("nested = {"));
1642
1643 let v2: Value = from_str(&output).unwrap();
1645 assert_eq!(v2["outer"], 1);
1646 assert_eq!(v2["nested.inner"], 2);
1647 }
1648
1649 #[test]
1650 fn test_ordering_with_mixed_types() {
1651 let input = r#"{
1652 string_first = "hello";
1653 int_second = 42;
1654 bool_third = true;
1655 float_fourth = 3.14;
1656 array_fifth = [1, 2, 3];
1657}"#;
1658 let v: Value = from_str(input).unwrap();
1659
1660 if let Value::Group(map) = &v {
1661 let keys: Vec<&String> = map.keys().collect();
1662 assert_eq!(
1663 keys,
1664 vec![
1665 "string_first",
1666 "int_second",
1667 "bool_third",
1668 "float_fourth",
1669 "array_fifth"
1670 ]
1671 );
1672 }
1673
1674 let output = Config::from(v).to_string().unwrap();
1675 let v2: Value = from_str(&output).unwrap();
1676
1677 if let Value::Group(map) = &v2 {
1679 let keys: Vec<&String> = map.keys().collect();
1680 assert_eq!(
1681 keys,
1682 vec![
1683 "string_first",
1684 "int_second",
1685 "bool_third",
1686 "float_fourth",
1687 "array_fifth"
1688 ]
1689 );
1690 }
1691 }
1692
1693 #[test]
1694 fn test_adding_new_keys_appends_to_end() {
1695 let input = "a = 1;\nb = 2;";
1696 let mut v: Value = from_str(input).unwrap();
1697
1698 v.set("c", Value::Integer(3)).unwrap();
1700
1701 if let Value::Group(map) = &v {
1702 let keys: Vec<&String> = map.keys().collect();
1703 assert_eq!(keys, vec!["a", "b", "c"]);
1704 }
1705
1706 let output = Config::from(v).to_string().unwrap();
1707
1708 let a_pos = output.find("a = 1").unwrap();
1710 let b_pos = output.find("b = 2").unwrap();
1711 let c_pos = output.find("c = 3").unwrap();
1712
1713 assert!(a_pos < b_pos);
1714 assert!(b_pos < c_pos);
1715 }
1716
1717 #[test]
1718 fn test_implicit_group_round_trip_exact() {
1719 let input = "name = \"test\";\nversion = 42;";
1720 let v: Value = from_str(input).unwrap();
1721 let output = Config::from(v).to_string().unwrap();
1722
1723 assert_eq!(output, input);
1725
1726 let v2: Value = from_str(&output).unwrap();
1728 let output2 = Config::from(v2).to_string().unwrap();
1729 assert_eq!(output, output2);
1730 }
1731
1732 #[test]
1733 fn test_nested_indentation() {
1734 let input = r#"{
1735 outer = 1;
1736 nested = {
1737 inner = 2;
1738 deep = {
1739 value = 3;
1740 };
1741 };
1742 another = 4;
1743}"#;
1744 let v: Value = from_str(input).unwrap();
1745 let output = Config::from(v).to_string().unwrap();
1746
1747 assert!(output.contains("outer = 1"));
1749 assert!(output.contains("nested = {"));
1750 assert!(output.contains(" inner = 2"));
1752 assert!(output.contains(" deep = {"));
1753 assert!(output.contains(" value = 3"));
1755
1756 let v2: Value = from_str(&output).unwrap();
1758 assert_eq!(v2["outer"], 1);
1759 assert_eq!(v2["nested.inner"], 2);
1760 assert_eq!(v2["nested.deep.value"], 3);
1761 assert_eq!(v2["another"], 4);
1762 }
1763
1764 #[test]
1765 fn test_implicit_group_with_nested_explicit_groups() {
1766 let input = r#"top_level = 1;
1767nested = {
1768 inner = 2;
1769};
1770also_top = 3;"#;
1771 let v: Value = from_str(input).unwrap();
1772 let output = Config::from(v).to_string().unwrap();
1773
1774 assert!(!output.trim().starts_with('{'));
1776
1777 assert!(output.contains("nested = {"));
1779 assert!(output.contains(" inner = 2"));
1780
1781 let v2: Value = from_str(&output).unwrap();
1783 assert_eq!(v2["top_level"], 1);
1784 assert_eq!(v2["nested.inner"], 2);
1785 assert_eq!(v2["also_top"], 3);
1786 }
1787
1788 #[test]
1789 fn test_deeply_nested_groups() {
1790 let input = r#"{
1791 level1 = {
1792 level2 = {
1793 level3 = {
1794 value = 42;
1795 };
1796 };
1797 };
1798}"#;
1799 let v: Value = from_str(input).unwrap();
1800 let output = Config::from(v).to_string().unwrap();
1801
1802 assert!(output.contains("level1 = {"));
1805 assert!(output.contains(" level2 = {"));
1806 assert!(output.contains(" level3 = {"));
1807 assert!(output.contains(" value = 42"));
1808 }
1809
1810 #[test]
1813 fn test_config_implicit_round_trip() {
1814 let input = "name = \"test\";\nversion = 42;";
1815 let config = Config::from_str(input).unwrap();
1816
1817 assert!(!config.explicit_braces);
1818 assert_eq!(config["name"], "test");
1819 assert_eq!(config["version"], 42);
1820
1821 let output = config.to_string().unwrap();
1822 assert_eq!(output, input);
1823 }
1824
1825 #[test]
1826 fn test_config_explicit_round_trip() {
1827 let input = "{\n name = \"test\";\n version = 42;\n}";
1828 let config = Config::from_str(input).unwrap();
1829
1830 assert!(config.explicit_braces);
1831 assert_eq!(config["name"], "test");
1832
1833 let output = config.to_string().unwrap();
1834 assert!(output.starts_with('{'));
1835 assert!(output.ends_with('}'));
1836 }
1837
1838 #[test]
1839 fn test_config_deref_lookup() {
1840 let config = Config::from_str("a = 1; b = { c = 2; };").unwrap();
1841
1842 assert_eq!(config.lookup("b.c").unwrap().as_i32(), Some(2));
1844 assert!(config.is_group());
1845 }
1846
1847 #[test]
1848 fn test_config_deref_mut() {
1849 let mut config = Config::from_str("a = 1; b = 2;").unwrap();
1850
1851 config.set("c", Value::Integer(3)).unwrap();
1852 assert_eq!(config["c"], 3);
1853
1854 let output = config.to_string().unwrap();
1855 assert!(output.contains("c = 3"));
1856 }
1857
1858 #[test]
1859 fn test_config_display() {
1860 let config = Config::from_str("x = 10; y = 20;").unwrap();
1861 let displayed = format!("{}", config);
1862 assert!(displayed.contains("x = 10"));
1863 assert!(displayed.contains("y = 20"));
1864 assert!(!displayed.starts_with('{'));
1865 }
1866
1867 #[test]
1868 fn test_config_new_empty() {
1869 let mut config = Config::new();
1870 assert!(!config.explicit_braces);
1871 assert!(config.is_group());
1872
1873 config.set("key", Value::String("val".to_string())).unwrap();
1874 let output = config.to_string().unwrap();
1875 assert_eq!(output, "key = \"val\";");
1876 }
1877
1878 #[test]
1879 fn test_config_from_value() {
1880 let mut map = Map::new();
1881 map.insert("key".to_string(), Value::String("val".to_string()));
1882 let config = Config::from(Value::Group(map));
1883
1884 assert!(!config.explicit_braces);
1885 let output = config.to_string().unwrap();
1886 assert_eq!(output, "key = \"val\";");
1887 }
1888
1889 #[test]
1890 fn test_config_from_value_explicit() {
1891 let mut map = Map::new();
1892 map.insert("key".to_string(), Value::String("val".to_string()));
1893 let mut config = Config::from(Value::Group(map));
1894 config.explicit_braces = true;
1895
1896 assert!(config.explicit_braces);
1897 let output = config.to_string().unwrap();
1898 assert!(output.starts_with('{'));
1899 assert!(output.contains("key = \"val\""));
1900 }
1901
1902 #[test]
1903 fn test_config_default() {
1904 let config = Config::default();
1905 assert!(!config.explicit_braces);
1906 assert!(config.is_group());
1907 assert_eq!(config.as_group().unwrap().len(), 0);
1908 }
1909
1910 #[test]
1911 fn test_config_serialize() {
1912 let config = Config::from_str("a = 1; b = 2;").unwrap();
1913 let serde_output = crate::to_string(&config).unwrap();
1915 assert!(serde_output.starts_with('{'));
1916
1917 let format_output = config.to_string().unwrap();
1919 assert!(!format_output.starts_with('{'));
1920 }
1921}