hocon_rs/raw/
raw_string.rs

1use derive_more::{Constructor, Deref, DerefMut};
2use std::fmt::{Debug, Display, Formatter};
3
4use crate::{
5    join, join_debug,
6    path::{Key, Path},
7    raw::raw_value::{
8        RAW_CONCAT_STRING_TYPE, RAW_MULTILINE_STRING_TYPE, RAW_QUOTED_STRING_TYPE,
9        RAW_UNQUOTED_STRING_TYPE,
10    },
11};
12
13/// Represents the different types of string values in a HOCON configuration.
14///
15/// This enum covers the three standard HOCON string types, plus an additional variant
16/// to handle path expressions.
17#[derive(Clone, Eq, PartialEq, Hash)]
18pub enum RawString {
19    /// A string literal enclosed in double quotes.
20    QuotedString(String),
21    /// A simple string without quotes.
22    UnquotedString(String),
23    /// A multiline string enclosed in three double quotes.
24    MultilineString(String),
25    /// A path expression
26    PathExpression(PathExpression),
27}
28
29#[derive(Clone, Eq, PartialEq, Hash, Constructor, Deref, DerefMut)]
30pub struct PathExpression(Vec<RawString>);
31
32impl PathExpression {
33    pub fn into_inner(self) -> Vec<RawString> {
34        self.0
35    }
36}
37
38impl Debug for PathExpression {
39    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40        join_debug(self.iter(), ".", f)
41    }
42}
43
44impl Display for PathExpression {
45    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46        join(self.iter(), ".", f)
47    }
48}
49
50impl From<&str> for RawString {
51    fn from(val: &str) -> Self {
52        if val.chars().any(|c| c == '\n') {
53            RawString::multiline(val)
54        } else {
55            RawString::quoted(val)
56        }
57    }
58}
59
60impl From<String> for RawString {
61    fn from(val: String) -> Self {
62        if val.chars().any(|c| c == '\n') {
63            RawString::multiline(val)
64        } else {
65            RawString::quoted(val)
66        }
67    }
68}
69
70impl RawString {
71    pub fn ty(&self) -> &'static str {
72        match self {
73            RawString::QuotedString(_) => RAW_QUOTED_STRING_TYPE,
74            RawString::UnquotedString(_) => RAW_UNQUOTED_STRING_TYPE,
75            RawString::MultilineString(_) => RAW_MULTILINE_STRING_TYPE,
76            RawString::PathExpression(_) => RAW_CONCAT_STRING_TYPE,
77        }
78    }
79
80    pub fn as_path(&self) -> Vec<&str> {
81        match self {
82            RawString::QuotedString(s)
83            | RawString::UnquotedString(s)
84            | RawString::MultilineString(s) => vec![s],
85            RawString::PathExpression(c) => c.iter().flat_map(|s| s.as_path()).collect(),
86        }
87    }
88
89    pub fn into_path(self) -> Path {
90        match self {
91            RawString::QuotedString(s)
92            | RawString::UnquotedString(s)
93            | RawString::MultilineString(s) => Path::new(Key::String(s), None),
94            RawString::PathExpression(c) => {
95                let mut dummy = Path::new(Key::String("".to_string()), None);
96                let mut curr = &mut dummy;
97                for path in c.into_inner() {
98                    curr.remainder = Some(Box::new(path.into_path()));
99                    curr = curr.remainder.as_mut().unwrap();
100                }
101                *dummy.remainder.expect("empty path found")
102            }
103        }
104    }
105
106    pub fn quoted(string: impl Into<String>) -> Self {
107        Self::QuotedString(string.into())
108    }
109
110    pub fn unquoted(string: impl Into<String>) -> Self {
111        Self::UnquotedString(string.into())
112    }
113
114    pub fn multiline(string: impl Into<String>) -> Self {
115        Self::MultilineString(string.into())
116    }
117
118    pub fn path_expression(paths: Vec<RawString>) -> Self {
119        Self::PathExpression(PathExpression::new(paths))
120    }
121}
122
123impl Display for RawString {
124    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
125        match self {
126            RawString::QuotedString(s) => write!(f, "{}", s),
127            RawString::UnquotedString(s) => write!(f, "{}", s),
128            RawString::MultilineString(s) => write!(f, "{}", s),
129            RawString::PathExpression(s) => write!(f, "{}", s),
130        }
131    }
132}
133
134impl Debug for RawString {
135    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
136        match self {
137            Self::QuotedString(s) => {
138                write!(f, "\"{:?}\"", s)
139            }
140            Self::UnquotedString(s) => {
141                write!(f, "{:?}", s)
142            }
143            Self::MultilineString(s) => {
144                write!(f, "\"\"\"{:?}\"\"\"", s)
145            }
146            Self::PathExpression(s) => {
147                write!(f, "{:?}", s)
148            }
149        }
150    }
151}