Skip to main content

libconfig/
de.rs

1//! Deserializer for libconfig format
2
3use std::cell::Cell;
4
5use serde::Deserialize;
6use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor};
7
8use crate::error::{Error, Result};
9
10thread_local! {
11    /// Tracks whether the current sequence being deserialized is a list `(...)`.
12    /// Used by ValueVisitor to distinguish Array from List.
13    static IS_LIST_CONTEXT: Cell<bool> = const { Cell::new(false) };
14}
15
16/// Returns true if the current deserialization context is a list.
17pub(crate) fn is_list_context() -> bool {
18    IS_LIST_CONTEXT.with(|c| c.get())
19}
20
21/// A structure that deserializes libconfig format into Rust values
22pub struct Deserializer<'de> {
23    input: &'de str,
24}
25
26impl<'de> Deserializer<'de> {
27    /// Create a deserializer from a `&str`
28    pub fn from_str(input: &'de str) -> Self {
29        Deserializer { input }
30    }
31
32    /// Look at the first character without consuming it
33    fn peek_char(&self) -> Result<char> {
34        self.input.chars().next().ok_or(Error::Eof)
35    }
36
37    /// Consume and return the next character
38    fn next_char(&mut self) -> Result<char> {
39        let ch = self.peek_char()?;
40        self.input = &self.input[ch.len_utf8()..];
41        Ok(ch)
42    }
43
44    /// Skip whitespace and comments
45    fn skip_whitespace(&mut self) {
46        loop {
47            // Skip whitespace
48            self.input = self.input.trim_start();
49
50            if self.input.is_empty() {
51                return;
52            }
53
54            // Check for comments
55            if self.input.starts_with('#') {
56                // Skip to end of line
57                if let Some(pos) = self.input.find('\n') {
58                    self.input = &self.input[pos + 1..];
59                } else {
60                    self.input = "";
61                    return;
62                }
63            } else if self.input.starts_with("//") {
64                // Skip to end of line
65                if let Some(pos) = self.input.find('\n') {
66                    self.input = &self.input[pos + 1..];
67                } else {
68                    self.input = "";
69                    return;
70                }
71            } else if self.input.starts_with("/*") {
72                // Skip to */
73                if let Some(pos) = self.input.find("*/") {
74                    self.input = &self.input[pos + 2..];
75                } else {
76                    self.input = "";
77                    return;
78                }
79            } else {
80                return;
81            }
82        }
83    }
84
85    /// Check if the input starts with an identifier followed by '=' or ':',
86    /// indicating the start of a setting in an implicit group.
87    /// This is used by `deserialize_any` to disambiguate between booleans
88    /// (true/false) and identifiers that happen to start with t/T/f/F.
89    fn is_implicit_group_start(&self) -> bool {
90        let input = self.input;
91
92        // Skip the identifier: [A-Za-z\*][-A-Za-z0-9_\*]*
93        let mut len = 0;
94        let mut first = true;
95        for ch in input.chars() {
96            if first {
97                if ch.is_ascii_alphabetic() || ch == '*' {
98                    len += ch.len_utf8();
99                    first = false;
100                } else {
101                    return false;
102                }
103            } else if ch.is_alphanumeric() || ch == '_' || ch == '-' || ch == '*' {
104                len += ch.len_utf8();
105            } else {
106                break;
107            }
108        }
109
110        if len == 0 {
111            return false;
112        }
113
114        // Skip whitespace after identifier
115        let rest = input[len..].trim_start();
116
117        // Check for '=' or ':'
118        matches!(rest.chars().next(), Some('=' | ':'))
119    }
120
121    /// Parse a boolean value (case-insensitive per libconfig spec)
122    fn parse_bool(&mut self) -> Result<bool> {
123        self.skip_whitespace();
124        if self.input.len() >= 4
125            && self.input[..4].eq_ignore_ascii_case("true")
126            && !self.input[4..]
127                .chars()
128                .next()
129                .map_or(false, |c| c.is_alphanumeric() || c == '_')
130        {
131            self.input = &self.input[4..];
132            Ok(true)
133        } else if self.input.len() >= 5
134            && self.input[..5].eq_ignore_ascii_case("false")
135            && !self.input[5..]
136                .chars()
137                .next()
138                .map_or(false, |c| c.is_alphanumeric() || c == '_')
139        {
140            self.input = &self.input[5..];
141            Ok(false)
142        } else {
143            Err(Error::ExpectedBoolean)
144        }
145    }
146
147    /// Parse an identifier (setting name)
148    /// Per spec: names must match `[A-Za-z*][-A-Za-z0-9_*]*`
149    fn parse_identifier(&mut self) -> Result<&'de str> {
150        self.skip_whitespace();
151        let start = self.input;
152        let mut len = 0;
153        let mut first = true;
154
155        for ch in self.input.chars() {
156            if first {
157                if ch.is_ascii_alphabetic() || ch == '*' {
158                    len += ch.len_utf8();
159                    first = false;
160                } else {
161                    break;
162                }
163            } else if ch.is_alphanumeric() || ch == '_' || ch == '-' || ch == '*' {
164                len += ch.len_utf8();
165            } else {
166                break;
167            }
168        }
169
170        if len == 0 {
171            return Err(Error::ExpectedIdentifier);
172        }
173
174        let ident = &start[..len];
175        self.input = &self.input[len..];
176        Ok(ident)
177    }
178
179    /// Parse a single quoted string (without adjacent concatenation)
180    fn parse_single_string(&mut self) -> Result<String> {
181        if self.next_char()? != '"' {
182            return Err(Error::ExpectedString);
183        }
184
185        let mut result = String::new();
186        let mut escape = false;
187
188        loop {
189            if self.input.is_empty() {
190                return Err(Error::Eof);
191            }
192
193            let ch = self.next_char()?;
194
195            if escape {
196                match ch {
197                    '"' => result.push('"'),
198                    '\\' => result.push('\\'),
199                    'n' => result.push('\n'),
200                    'r' => result.push('\r'),
201                    't' => result.push('\t'),
202                    'f' => result.push('\x0C'),
203                    'b' => result.push('\x08'),
204                    'v' => result.push('\x0B'),
205                    'a' => result.push('\x07'),
206                    'x' => {
207                        // Parse hex escape \xNN
208                        if self.input.len() < 2 {
209                            return Err(Error::InvalidEscape);
210                        }
211                        let hex = &self.input[..2];
212                        if let Ok(byte) = u8::from_str_radix(hex, 16) {
213                            result.push(byte as char);
214                            self.input = &self.input[2..];
215                        } else {
216                            return Err(Error::InvalidEscape);
217                        }
218                    }
219                    _ => return Err(Error::InvalidEscape),
220                }
221                escape = false;
222            } else if ch == '\\' {
223                escape = true;
224            } else if ch == '"' {
225                break;
226            } else {
227                result.push(ch);
228            }
229        }
230
231        Ok(result)
232    }
233
234    /// Parse a string value with adjacent string concatenation
235    /// Per spec: "hello" " world" => "hello world"
236    fn parse_string(&mut self) -> Result<String> {
237        self.skip_whitespace();
238        let mut result = self.parse_single_string()?;
239
240        // Check for adjacent strings (concatenation)
241        loop {
242            self.skip_whitespace();
243            if self.input.starts_with('"') {
244                result.push_str(&self.parse_single_string()?);
245            } else {
246                break;
247            }
248        }
249
250        Ok(result)
251    }
252
253    /// Parse a number (integer or float)
254    fn parse_number(&mut self) -> Result<Number> {
255        self.skip_whitespace();
256        let start = self.input;
257        let mut len = 0;
258        let mut is_float = false;
259        let mut is_long = false;
260        let mut is_hex = false;
261        let mut is_binary = false;
262        let mut is_octal = false;
263        let mut has_sign = false;
264
265        // Check for sign
266        if let Some(ch) = self.input.chars().next() {
267            if ch == '-' || ch == '+' {
268                has_sign = true;
269                len += 1;
270            }
271        }
272
273        // Check for leading decimal point (e.g. .5)
274        if self.input[len..].starts_with('.') {
275            is_float = true;
276            len += 1;
277        }
278        // Check for hex (0x), binary (0b), or octal (0o/0q) — no sign allowed
279        else if !has_sign
280            && (self.input[len..].starts_with("0x") || self.input[len..].starts_with("0X"))
281        {
282            is_hex = true;
283            len += 2;
284        } else if !has_sign
285            && (self.input[len..].starts_with("0b") || self.input[len..].starts_with("0B"))
286        {
287            is_binary = true;
288            len += 2;
289        } else if !has_sign
290            && (self.input[len..].starts_with("0o")
291                || self.input[len..].starts_with("0O")
292                || self.input[len..].starts_with("0q")
293                || self.input[len..].starts_with("0Q"))
294        {
295            is_octal = true;
296            len += 2;
297        }
298
299        // Parse digits
300        let mut digit_count = 0usize;
301        for ch in self.input[len..].chars() {
302            if is_hex && ch.is_ascii_hexdigit() {
303                len += ch.len_utf8();
304                digit_count += 1;
305            } else if is_binary && (ch == '0' || ch == '1') {
306                len += ch.len_utf8();
307                digit_count += 1;
308            } else if is_octal && ch.is_digit(8) {
309                len += ch.len_utf8();
310                digit_count += 1;
311            } else if !is_hex && !is_binary && !is_octal && ch.is_ascii_digit() {
312                len += ch.len_utf8();
313                digit_count += 1;
314            } else if ch == '.' && !is_hex && !is_binary && !is_octal && !is_float {
315                is_float = true;
316                len += ch.len_utf8();
317            } else if (ch == 'e' || ch == 'E') && !is_hex && !is_binary && !is_octal {
318                is_float = true;
319                len += ch.len_utf8();
320                // Check for sign after exponent
321                if let Some(next_ch) = self.input[len..].chars().next() {
322                    if next_ch == '+' || next_ch == '-' {
323                        len += 1;
324                    }
325                }
326            } else if ch == 'L' {
327                is_long = true;
328                len += ch.len_utf8();
329                break;
330            } else {
331                break;
332            }
333        }
334
335        if len == 0
336            || (len == 1 && has_sign)
337            || (is_float && digit_count == 0)
338            || ((is_hex || is_binary || is_octal) && digit_count == 0)
339        {
340            return Err(Error::ExpectedInteger);
341        }
342
343        let num_str = &start[..len];
344        self.input = &self.input[len..];
345
346        if is_float {
347            let val = num_str.parse::<f64>().map_err(|_| Error::InvalidNumber)?;
348            Ok(Number::Float(val))
349        } else if is_hex {
350            let hex_str = num_str
351                .trim_start_matches("0x")
352                .trim_start_matches("0X")
353                .trim_end_matches('L');
354            let val = i64::from_str_radix(hex_str, 16).map_err(|_| Error::InvalidNumber)?;
355            if is_long || digit_count > 8 {
356                Ok(Number::I64(val))
357            } else {
358                Ok(Number::I32(val as i32))
359            }
360        } else if is_binary {
361            let bin_str = num_str
362                .trim_start_matches("0b")
363                .trim_start_matches("0B")
364                .trim_end_matches('L');
365            let val = i64::from_str_radix(bin_str, 2).map_err(|_| Error::InvalidNumber)?;
366            if is_long || digit_count > 32 {
367                Ok(Number::I64(val))
368            } else {
369                Ok(Number::I32(val as i32))
370            }
371        } else if is_octal {
372            let oct_str = num_str
373                .trim_start_matches("0o")
374                .trim_start_matches("0O")
375                .trim_start_matches("0q")
376                .trim_start_matches("0Q")
377                .trim_end_matches('L');
378            let val = i64::from_str_radix(oct_str, 8).map_err(|_| Error::InvalidNumber)?;
379            if is_long || digit_count > 10 {
380                Ok(Number::I64(val))
381            } else {
382                Ok(Number::I32(val as i32))
383            }
384        } else {
385            let trimmed = num_str.trim_end_matches('L');
386            if is_long {
387                let val = trimmed.parse::<i64>().map_err(|_| Error::InvalidNumber)?;
388                Ok(Number::I64(val))
389            } else {
390                // Auto-promote to i64 if value exceeds i32 range
391                match trimmed.parse::<i32>() {
392                    Ok(val) => Ok(Number::I32(val)),
393                    Err(_) => {
394                        let val = trimmed.parse::<i64>().map_err(|_| Error::InvalidNumber)?;
395                        Ok(Number::I64(val))
396                    }
397                }
398            }
399        }
400    }
401}
402
403/// Deserialize an instance of type `T` from a string of libconfig text
404pub fn from_str<'a, T>(s: &'a str) -> Result<T>
405where
406    T: Deserialize<'a>,
407{
408    let mut deserializer = Deserializer::from_str(s);
409    let t = T::deserialize(&mut deserializer)?;
410    deserializer.skip_whitespace();
411    if deserializer.input.is_empty() {
412        Ok(t)
413    } else {
414        Err(Error::TrailingCharacters)
415    }
416}
417
418#[derive(Debug, Clone)]
419enum Number {
420    I32(i32),
421    I64(i64),
422    Float(f64),
423}
424
425impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
426    type Error = Error;
427
428    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
429    where
430        V: Visitor<'de>,
431    {
432        self.skip_whitespace();
433        match self.peek_char()? {
434            't' | 'T' | 'f' | 'F' => {
435                // Could be a boolean OR the start of an identifier in an implicit group.
436                // Look ahead: if this is an identifier followed by '=' or ':', it's a setting.
437                if self.is_implicit_group_start() {
438                    visitor.visit_map(ImplicitGroupAccess::new(self))
439                } else {
440                    self.deserialize_bool(visitor)
441                }
442            }
443            '"' => self.deserialize_string(visitor),
444            '[' => self.deserialize_seq(visitor),
445            '(' => self.deserialize_seq(visitor), // Lists are treated as sequences
446            '{' => self.deserialize_map(visitor),
447            '-' | '+' | '0'..='9' | '.' => {
448                // Try to parse as number
449                let num = self.parse_number()?;
450                match num {
451                    Number::I32(v) => visitor.visit_i32(v),
452                    Number::I64(v) => visitor.visit_i64(v),
453                    Number::Float(v) => visitor.visit_f64(v),
454                }
455            }
456            c if c.is_ascii_alphabetic() || c == '*' => {
457                // Starts with a letter or '*' — must be an implicit group setting
458                visitor.visit_map(ImplicitGroupAccess::new(self))
459            }
460            _ => Err(Error::Syntax),
461        }
462    }
463
464    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
465    where
466        V: Visitor<'de>,
467    {
468        visitor.visit_bool(self.parse_bool()?)
469    }
470
471    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
472    where
473        V: Visitor<'de>,
474    {
475        let num = self.parse_number()?;
476        match num {
477            Number::I32(v) => visitor.visit_i8(v as i8),
478            Number::I64(v) => visitor.visit_i8(v as i8),
479            Number::Float(v) => visitor.visit_i8(v as i8),
480        }
481    }
482
483    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
484    where
485        V: Visitor<'de>,
486    {
487        let num = self.parse_number()?;
488        match num {
489            Number::I32(v) => visitor.visit_i16(v as i16),
490            Number::I64(v) => visitor.visit_i16(v as i16),
491            Number::Float(v) => visitor.visit_i16(v as i16),
492        }
493    }
494
495    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
496    where
497        V: Visitor<'de>,
498    {
499        let num = self.parse_number()?;
500        match num {
501            Number::I32(v) => visitor.visit_i32(v),
502            Number::I64(v) => visitor.visit_i32(v as i32),
503            Number::Float(v) => visitor.visit_i32(v as i32),
504        }
505    }
506
507    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
508    where
509        V: Visitor<'de>,
510    {
511        let num = self.parse_number()?;
512        match num {
513            Number::I32(v) => visitor.visit_i64(v as i64),
514            Number::I64(v) => visitor.visit_i64(v),
515            Number::Float(v) => visitor.visit_i64(v as i64),
516        }
517    }
518
519    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
520    where
521        V: Visitor<'de>,
522    {
523        let num = self.parse_number()?;
524        match num {
525            Number::I32(v) => visitor.visit_u8(v as u8),
526            Number::I64(v) => visitor.visit_u8(v as u8),
527            Number::Float(v) => visitor.visit_u8(v as u8),
528        }
529    }
530
531    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
532    where
533        V: Visitor<'de>,
534    {
535        let num = self.parse_number()?;
536        match num {
537            Number::I32(v) => visitor.visit_u16(v as u16),
538            Number::I64(v) => visitor.visit_u16(v as u16),
539            Number::Float(v) => visitor.visit_u16(v as u16),
540        }
541    }
542
543    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
544    where
545        V: Visitor<'de>,
546    {
547        let num = self.parse_number()?;
548        match num {
549            Number::I32(v) => visitor.visit_u32(v as u32),
550            Number::I64(v) => visitor.visit_u32(v as u32),
551            Number::Float(v) => visitor.visit_u32(v as u32),
552        }
553    }
554
555    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
556    where
557        V: Visitor<'de>,
558    {
559        let num = self.parse_number()?;
560        match num {
561            Number::I32(v) => visitor.visit_u64(v as u64),
562            Number::I64(v) => visitor.visit_u64(v as u64),
563            Number::Float(v) => visitor.visit_u64(v as u64),
564        }
565    }
566
567    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
568    where
569        V: Visitor<'de>,
570    {
571        let num = self.parse_number()?;
572        match num {
573            Number::I32(v) => visitor.visit_f32(v as f32),
574            Number::I64(v) => visitor.visit_f32(v as f32),
575            Number::Float(v) => visitor.visit_f32(v as f32),
576        }
577    }
578
579    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
580    where
581        V: Visitor<'de>,
582    {
583        let num = self.parse_number()?;
584        match num {
585            Number::I32(v) => visitor.visit_f64(v as f64),
586            Number::I64(v) => visitor.visit_f64(v as f64),
587            Number::Float(v) => visitor.visit_f64(v),
588        }
589    }
590
591    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
592    where
593        V: Visitor<'de>,
594    {
595        let s = self.parse_string()?;
596        let mut chars = s.chars();
597        let ch = chars.next().ok_or(Error::ExpectedString)?;
598        if chars.next().is_some() {
599            return Err(Error::ExpectedString);
600        }
601        visitor.visit_char(ch)
602    }
603
604    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
605    where
606        V: Visitor<'de>,
607    {
608        self.skip_whitespace();
609        // Check if it's a quoted string or an identifier (for map keys)
610        if self.peek_char()? == '"' {
611            visitor.visit_string(self.parse_string()?)
612        } else {
613            // It's an identifier (unquoted)
614            visitor.visit_str(self.parse_identifier()?)
615        }
616    }
617
618    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
619    where
620        V: Visitor<'de>,
621    {
622        self.skip_whitespace();
623        // Check if it's a quoted string or an identifier (for map keys)
624        if self.peek_char()? == '"' {
625            visitor.visit_string(self.parse_string()?)
626        } else {
627            // It's an identifier (unquoted)
628            visitor.visit_string(self.parse_identifier()?.to_string())
629        }
630    }
631
632    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
633    where
634        V: Visitor<'de>,
635    {
636        self.deserialize_seq(visitor)
637    }
638
639    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
640    where
641        V: Visitor<'de>,
642    {
643        self.deserialize_seq(visitor)
644    }
645
646    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
647    where
648        V: Visitor<'de>,
649    {
650        visitor.visit_some(self)
651    }
652
653    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
654    where
655        V: Visitor<'de>,
656    {
657        visitor.visit_unit()
658    }
659
660    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
661    where
662        V: Visitor<'de>,
663    {
664        self.deserialize_unit(visitor)
665    }
666
667    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
668    where
669        V: Visitor<'de>,
670    {
671        visitor.visit_newtype_struct(self)
672    }
673
674    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
675    where
676        V: Visitor<'de>,
677    {
678        self.skip_whitespace();
679        let ch = self.peek_char()?;
680
681        if ch == '[' {
682            self.next_char()?;
683            IS_LIST_CONTEXT.with(|c| c.set(false));
684            let value = visitor.visit_seq(ArrayAccess::new(self, ']', false))?;
685            self.skip_whitespace();
686            if self.next_char()? == ']' {
687                Ok(value)
688            } else {
689                Err(Error::ExpectedArrayEnd)
690            }
691        } else if ch == '(' {
692            self.next_char()?;
693            IS_LIST_CONTEXT.with(|c| c.set(true));
694            let value = visitor.visit_seq(ArrayAccess::new(self, ')', true))?;
695            self.skip_whitespace();
696            if self.next_char()? == ')' {
697                Ok(value)
698            } else {
699                Err(Error::ExpectedListEnd)
700            }
701        } else {
702            Err(Error::ExpectedArray)
703        }
704    }
705
706    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
707    where
708        V: Visitor<'de>,
709    {
710        self.deserialize_seq(visitor)
711    }
712
713    fn deserialize_tuple_struct<V>(
714        self,
715        _name: &'static str,
716        _len: usize,
717        visitor: V,
718    ) -> Result<V::Value>
719    where
720        V: Visitor<'de>,
721    {
722        self.deserialize_seq(visitor)
723    }
724
725    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
726    where
727        V: Visitor<'de>,
728    {
729        self.skip_whitespace();
730        if self.next_char()? == '{' {
731            let value = visitor.visit_map(GroupAccess::new(self))?;
732            self.skip_whitespace();
733            if self.next_char()? == '}' {
734                Ok(value)
735            } else {
736                Err(Error::ExpectedGroupEnd)
737            }
738        } else {
739            Err(Error::ExpectedGroup)
740        }
741    }
742
743    fn deserialize_struct<V>(
744        self,
745        _name: &'static str,
746        _fields: &'static [&'static str],
747        visitor: V,
748    ) -> Result<V::Value>
749    where
750        V: Visitor<'de>,
751    {
752        self.skip_whitespace();
753        // Check if the struct is wrapped in braces or is a top-level implicit group
754        if self.peek_char()? == '{' {
755            self.deserialize_map(visitor)
756        } else {
757            // Top-level struct without explicit braces - treat as implicit group
758            let value = visitor.visit_map(ImplicitGroupAccess::new(self))?;
759            Ok(value)
760        }
761    }
762
763    fn deserialize_enum<V>(
764        self,
765        _name: &'static str,
766        _variants: &'static [&'static str],
767        visitor: V,
768    ) -> Result<V::Value>
769    where
770        V: Visitor<'de>,
771    {
772        self.skip_whitespace();
773        if self.peek_char()? == '"' {
774            // Unit variant
775            visitor.visit_enum(self.parse_string()?.into_deserializer())
776        } else {
777            // Other variant types - not fully supported yet
778            Err(Error::TypeNotSupported("complex enum variants".to_string()))
779        }
780    }
781
782    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
783    where
784        V: Visitor<'de>,
785    {
786        visitor.visit_str(self.parse_identifier()?)
787    }
788
789    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
790    where
791        V: Visitor<'de>,
792    {
793        self.deserialize_any(visitor)
794    }
795}
796
797struct ArrayAccess<'a, 'de: 'a> {
798    de: &'a mut Deserializer<'de>,
799    first: bool,
800    end_char: char,
801    is_list: bool,
802}
803
804impl<'a, 'de> ArrayAccess<'a, 'de> {
805    fn new(de: &'a mut Deserializer<'de>, end_char: char, is_list: bool) -> Self {
806        ArrayAccess {
807            de,
808            first: true,
809            end_char,
810            is_list,
811        }
812    }
813}
814
815impl<'de, 'a> SeqAccess<'de> for ArrayAccess<'a, 'de> {
816    type Error = Error;
817
818    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
819    where
820        T: DeserializeSeed<'de>,
821    {
822        self.de.skip_whitespace();
823
824        // Check if we're at the end
825        if self.de.peek_char()? == self.end_char {
826            return Ok(None);
827        }
828
829        // Require comma between elements (except first)
830        if !self.first {
831            if self.de.peek_char()? == ',' {
832                self.de.next_char()?;
833                self.de.skip_whitespace();
834                // Check for trailing comma
835                if self.de.peek_char()? == self.end_char {
836                    return Ok(None);
837                }
838            } else {
839                return Err(Error::ExpectedArrayComma);
840            }
841        }
842        self.first = false;
843
844        // Set thread-local so ValueVisitor can distinguish Array vs List
845        IS_LIST_CONTEXT.with(|c| c.set(self.is_list));
846
847        seed.deserialize(&mut *self.de).map(Some)
848    }
849}
850
851struct GroupAccess<'a, 'de: 'a> {
852    de: &'a mut Deserializer<'de>,
853    first: bool,
854}
855
856impl<'a, 'de> GroupAccess<'a, 'de> {
857    fn new(de: &'a mut Deserializer<'de>) -> Self {
858        GroupAccess { de, first: true }
859    }
860}
861
862struct ImplicitGroupAccess<'a, 'de: 'a> {
863    de: &'a mut Deserializer<'de>,
864    first: bool,
865}
866
867impl<'a, 'de> ImplicitGroupAccess<'a, 'de> {
868    fn new(de: &'a mut Deserializer<'de>) -> Self {
869        ImplicitGroupAccess { de, first: true }
870    }
871}
872
873impl<'de, 'a> MapAccess<'de> for GroupAccess<'a, 'de> {
874    type Error = Error;
875
876    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
877    where
878        K: DeserializeSeed<'de>,
879    {
880        self.de.skip_whitespace();
881
882        // Check if we're at the end
883        if self.de.peek_char()? == '}' {
884            return Ok(None);
885        }
886
887        // Require semicolon or comma between settings (except first)
888        if !self.first {
889            let ch = self.de.peek_char()?;
890            if ch == ';' || ch == ',' {
891                self.de.next_char()?;
892                self.de.skip_whitespace();
893                // Check for trailing separator
894                if self.de.peek_char()? == '}' {
895                    return Ok(None);
896                }
897            }
898            // Semicolons are optional, so don't error if missing
899        }
900        self.first = false;
901
902        seed.deserialize(&mut *self.de).map(Some)
903    }
904
905    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
906    where
907        V: DeserializeSeed<'de>,
908    {
909        self.de.skip_whitespace();
910
911        // Expect '=' or ':'
912        let ch = self.de.next_char()?;
913        if ch != '=' && ch != ':' {
914            return Err(Error::ExpectedEquals);
915        }
916
917        seed.deserialize(&mut *self.de)
918    }
919}
920
921impl<'de, 'a> MapAccess<'de> for ImplicitGroupAccess<'a, 'de> {
922    type Error = Error;
923
924    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
925    where
926        K: DeserializeSeed<'de>,
927    {
928        self.de.skip_whitespace();
929
930        // Check if we're at the end (end of input)
931        if self.de.input.is_empty() {
932            return Ok(None);
933        }
934
935        // Require semicolon or comma between settings (except first)
936        if !self.first {
937            let ch = self.de.peek_char()?;
938            if ch == ';' || ch == ',' {
939                self.de.next_char()?;
940                self.de.skip_whitespace();
941                // Check for trailing separator
942                if self.de.input.is_empty() {
943                    return Ok(None);
944                }
945            }
946            // Semicolons are optional, so don't error if missing
947        }
948        self.first = false;
949
950        seed.deserialize(&mut *self.de).map(Some)
951    }
952
953    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
954    where
955        V: DeserializeSeed<'de>,
956    {
957        self.de.skip_whitespace();
958
959        // Expect '=' or ':'
960        let ch = self.de.next_char()?;
961        if ch != '=' && ch != ':' {
962            return Err(Error::ExpectedEquals);
963        }
964
965        seed.deserialize(&mut *self.de)
966    }
967}
968
969#[cfg(test)]
970mod tests {
971    use super::*;
972    use serde::Deserialize;
973
974    #[test]
975    fn test_deserialize_primitives() {
976        assert_eq!(from_str::<u32>("42").unwrap(), 42);
977        assert_eq!(from_str::<i64>("42L").unwrap(), 42);
978        assert_eq!(from_str::<f64>("3.14").unwrap(), 3.14);
979        assert_eq!(from_str::<bool>("true").unwrap(), true);
980        assert_eq!(from_str::<String>("\"hello\"").unwrap(), "hello");
981    }
982
983    #[test]
984    fn test_deserialize_array() {
985        let arr: Vec<i32> = from_str("[1, 2, 3]").unwrap();
986        assert_eq!(arr, vec![1, 2, 3]);
987    }
988
989    #[test]
990    fn test_deserialize_struct() {
991        #[derive(Debug, Deserialize, PartialEq)]
992        struct Test {
993            a: i32,
994            b: String,
995        }
996
997        let input = r#"{ a = 42; b = "hello"; }"#;
998        let result: Test = from_str(input).unwrap();
999        assert_eq!(
1000            result,
1001            Test {
1002                a: 42,
1003                b: "hello".to_string()
1004            }
1005        );
1006    }
1007
1008    #[test]
1009    fn test_deserialize_with_comments() {
1010        let input = r#"
1011            # This is a comment
1012            {
1013                // Another comment
1014                a = 42; /* inline comment */
1015                b = "hello";
1016            }
1017        "#;
1018
1019        #[derive(Debug, Deserialize, PartialEq)]
1020        struct Test {
1021            a: i32,
1022            b: String,
1023        }
1024
1025        let result: Test = from_str(input).unwrap();
1026        assert_eq!(
1027            result,
1028            Test {
1029                a: 42,
1030                b: "hello".to_string()
1031            }
1032        );
1033    }
1034
1035    #[test]
1036    fn test_case_insensitive_booleans() {
1037        assert_eq!(from_str::<bool>("true").unwrap(), true);
1038        assert_eq!(from_str::<bool>("True").unwrap(), true);
1039        assert_eq!(from_str::<bool>("TRUE").unwrap(), true);
1040        assert_eq!(from_str::<bool>("false").unwrap(), false);
1041        assert_eq!(from_str::<bool>("False").unwrap(), false);
1042        assert_eq!(from_str::<bool>("FALSE").unwrap(), false);
1043        assert_eq!(from_str::<bool>("FaLsE").unwrap(), false);
1044    }
1045
1046    #[test]
1047    fn test_bool_word_boundary() {
1048        // "trueblah" should not parse as bool true
1049        assert!(from_str::<bool>("trueblah").is_err());
1050        assert!(from_str::<bool>("falsehood").is_err());
1051    }
1052
1053    #[test]
1054    fn test_adjacent_string_concatenation() {
1055        let result: String = from_str(r#""hello" " world""#).unwrap();
1056        assert_eq!(result, "hello world");
1057
1058        let result: String = from_str(r#""a" "b" "c""#).unwrap();
1059        assert_eq!(result, "abc");
1060    }
1061
1062    #[test]
1063    fn test_integer_auto_promotion() {
1064        // Value exceeding i32 range should auto-promote to i64
1065        let val: i64 = from_str("3000000000").unwrap();
1066        assert_eq!(val, 3_000_000_000i64);
1067    }
1068
1069    #[test]
1070    fn test_hex_binary_octal() {
1071        assert_eq!(from_str::<i32>("0xFF").unwrap(), 255);
1072        assert_eq!(from_str::<i32>("0b1010").unwrap(), 10);
1073        assert_eq!(from_str::<i32>("0o17").unwrap(), 15);
1074        assert_eq!(from_str::<i32>("0q17").unwrap(), 15);
1075    }
1076
1077    #[test]
1078    fn test_hex_auto_promotion_by_digit_count() {
1079        // 9+ hex digits should auto-promote to i64
1080        let val: i64 = from_str("0x1FFFFFFFF").unwrap();
1081        assert_eq!(val, 0x1FFFFFFFFi64);
1082    }
1083
1084    #[test]
1085    fn test_float_leading_dot() {
1086        let val: f64 = from_str(".5").unwrap();
1087        assert_eq!(val, 0.5);
1088    }
1089
1090    #[test]
1091    fn test_list_deserialization() {
1092        let arr: Vec<i32> = from_str("(1, 2, 3)").unwrap();
1093        assert_eq!(arr, vec![1, 2, 3]);
1094    }
1095
1096    #[test]
1097    fn test_implicit_group_as_value() {
1098        use crate::Value;
1099
1100        let raw_string = r#"
1101            title = "My HTTP server";
1102            listen_ports = [ 80, 443 ];
1103            misc = {
1104                owner = "Chuck Norris";
1105                location = "CA";
1106                contact = {
1107                    phone = "415-256-9999";
1108                    emails = ["chuck@norris.com", "chuck.norris@gmail.com"];
1109                };
1110            };"#;
1111
1112        let parsed_value: Value = from_str(raw_string).expect("Failed to parse value");
1113        assert_eq!(parsed_value["title"], "My HTTP server");
1114        assert_eq!(parsed_value["listen_ports"][0], 80);
1115        assert_eq!(parsed_value["listen_ports"][1], 443);
1116        assert_eq!(parsed_value["misc"]["owner"], "Chuck Norris");
1117        assert_eq!(parsed_value["misc"]["contact"]["phone"], "415-256-9999");
1118    }
1119
1120    #[test]
1121    fn test_implicit_group_bool_key() {
1122        // Identifiers starting with t/f should work as setting names
1123        use crate::Value;
1124
1125        let input = r#"flag = true; total = 100;"#;
1126        let v: Value = from_str(input).expect("Failed to parse");
1127        assert_eq!(v["flag"], true);
1128        assert_eq!(v["total"], 100);
1129    }
1130
1131    #[test]
1132    fn test_standalone_bool_still_works() {
1133        // Plain booleans without '=' should still parse as booleans
1134        assert_eq!(from_str::<bool>("true").unwrap(), true);
1135        assert_eq!(from_str::<bool>("false").unwrap(), false);
1136
1137        use crate::Value;
1138        let v: Value = from_str("true").unwrap();
1139        assert_eq!(v, Value::Bool(true));
1140
1141        let v: Value = from_str("false").unwrap();
1142        assert_eq!(v, Value::Bool(false));
1143    }
1144
1145    #[test]
1146    fn test_optional_semicolons() {
1147        #[derive(Debug, Deserialize, PartialEq)]
1148        struct Test {
1149            a: i32,
1150            b: i32,
1151            c: i32,
1152        }
1153
1154        // With semicolons
1155        let result: Test = from_str(r#"{ a = 1; b = 2; c = 3; }"#).unwrap();
1156        assert_eq!(result, Test { a: 1, b: 2, c: 3 });
1157
1158        // Without semicolons (settings separated only by whitespace)
1159        let result: Test = from_str("{ a = 1\n b = 2\n c = 3 }").unwrap();
1160        assert_eq!(result, Test { a: 1, b: 2, c: 3 });
1161
1162        // Mixed: some with, some without
1163        let result: Test = from_str("{ a = 1; b = 2\n c = 3 }").unwrap();
1164        assert_eq!(result, Test { a: 1, b: 2, c: 3 });
1165
1166        // Trailing semicolon before closing brace
1167        let result: Test = from_str(r#"{ a = 1; b = 2; c = 3; }"#).unwrap();
1168        assert_eq!(result, Test { a: 1, b: 2, c: 3 });
1169    }
1170
1171    #[test]
1172    fn test_commas_as_setting_separators() {
1173        #[derive(Debug, Deserialize, PartialEq)]
1174        struct Test {
1175            a: i32,
1176            b: i32,
1177            c: i32,
1178        }
1179
1180        // Commas instead of semicolons
1181        let result: Test = from_str(r#"{ a = 1, b = 2, c = 3 }"#).unwrap();
1182        assert_eq!(result, Test { a: 1, b: 2, c: 3 });
1183
1184        // Trailing comma before closing brace
1185        let result: Test = from_str(r#"{ a = 1, b = 2, c = 3, }"#).unwrap();
1186        assert_eq!(result, Test { a: 1, b: 2, c: 3 });
1187    }
1188
1189    #[test]
1190    fn test_optional_separators_in_implicit_group() {
1191        use crate::Value;
1192
1193        // Implicit group (no braces) without semicolons
1194        let v: Value = from_str("a = 1\nb = 2\nc = 3").unwrap();
1195        assert_eq!(v["a"], 1);
1196        assert_eq!(v["b"], 2);
1197        assert_eq!(v["c"], 3);
1198
1199        // Implicit group with semicolons
1200        let v: Value = from_str("a = 1; b = 2; c = 3;").unwrap();
1201        assert_eq!(v["a"], 1);
1202        assert_eq!(v["b"], 2);
1203        assert_eq!(v["c"], 3);
1204    }
1205
1206    #[test]
1207    fn test_auto_promotion_i64_via_value() {
1208        use crate::Value;
1209
1210        // i32 range value stays as Integer
1211        let v: Value = from_str("42").unwrap();
1212        assert!(v.is_i32());
1213        assert_eq!(v, Value::Integer(42));
1214
1215        // Value exceeding i32::MAX auto-promotes to Integer64
1216        let v: Value = from_str("3000000000").unwrap();
1217        assert!(v.is_i64());
1218        assert_eq!(v.as_i64(), Some(3_000_000_000i64));
1219
1220        // Explicit L suffix produces Integer64
1221        let v: Value = from_str("42L").unwrap();
1222        assert!(v.is_i64());
1223        assert_eq!(v.as_i64(), Some(42i64));
1224
1225        // Negative value exceeding i32::MIN auto-promotes to Integer64
1226        let v: Value = from_str("-3000000000").unwrap();
1227        assert!(v.is_i64());
1228        assert_eq!(v.as_i64(), Some(-3_000_000_000i64));
1229
1230        // i32::MAX is still i32
1231        let v: Value = from_str("2147483647").unwrap();
1232        assert!(v.is_i32());
1233
1234        // i32::MAX + 1 promotes to i64
1235        let v: Value = from_str("2147483648").unwrap();
1236        assert!(v.is_i64());
1237    }
1238
1239    #[test]
1240    fn test_negative_numbers() {
1241        // Negative integer
1242        assert_eq!(from_str::<i32>("-42").unwrap(), -42);
1243        assert_eq!(from_str::<i32>("-1").unwrap(), -1);
1244
1245        // Negative i64
1246        assert_eq!(from_str::<i64>("-42L").unwrap(), -42);
1247
1248        // Negative float
1249        assert_eq!(from_str::<f64>("-3.14").unwrap(), -3.14);
1250        assert_eq!(from_str::<f64>("-0.5").unwrap(), -0.5);
1251
1252        // Negative in a struct
1253        #[derive(Debug, Deserialize, PartialEq)]
1254        struct Coords {
1255            x: i32,
1256            y: i32,
1257            z: f64,
1258        }
1259
1260        let result: Coords = from_str(r#"{ x = -10; y = -20; z = -1.5; }"#).unwrap();
1261        assert_eq!(
1262            result,
1263            Coords {
1264                x: -10,
1265                y: -20,
1266                z: -1.5,
1267            }
1268        );
1269
1270        // Negative via Value
1271        use crate::Value;
1272        let v: Value = from_str("-42").unwrap();
1273        assert_eq!(v, Value::Integer(-42));
1274
1275        let v: Value = from_str("-3.14").unwrap();
1276        assert_eq!(v, Value::Float(-3.14));
1277    }
1278
1279    #[test]
1280    fn test_identifier_must_start_with_letter_or_asterisk() {
1281        #[derive(Debug, Deserialize)]
1282        #[allow(dead_code)]
1283        struct Test {
1284            a: i32,
1285        }
1286        // Valid identifiers
1287        let _: Test = from_str(r#"{ a = 1; }"#).unwrap();
1288
1289        // Identifier starting with digit should fail
1290        assert!(from_str::<Test>(r#"{ 1a = 1; }"#).is_err());
1291    }
1292}