1 | use std::borrow::Cow; |
2 | use std::str::FromStr; |
3 | |
4 | use crate::encode::{to_string_repr, StringStyle}; |
5 | use crate::parser; |
6 | use crate::parser::key::is_unquoted_char; |
7 | use crate::repr::{Decor, Repr}; |
8 | use crate::InternalString; |
9 | |
10 | /// Key as part of a Key/Value Pair or a table header. |
11 | /// |
12 | /// # Examples |
13 | /// |
14 | /// ```notrust |
15 | /// [dependencies."nom"] |
16 | /// version = "5.0" |
17 | /// 'literal key' = "nonsense" |
18 | /// "basic string key" = 42 |
19 | /// ``` |
20 | /// |
21 | /// There are 3 types of keys: |
22 | /// |
23 | /// 1. Bare keys (`version` and `dependencies`) |
24 | /// |
25 | /// 2. Basic quoted keys (`"basic string key"` and `"nom"`) |
26 | /// |
27 | /// 3. Literal quoted keys (`'literal key'`) |
28 | /// |
29 | /// For details see [toml spec](https://github.com/toml-lang/toml/#keyvalue-pair). |
30 | /// |
31 | /// To parse a key use `FromStr` trait implementation: `"string".parse::<Key>()`. |
32 | #[derive (Debug)] |
33 | pub struct Key { |
34 | key: InternalString, |
35 | pub(crate) repr: Option<Repr>, |
36 | pub(crate) decor: Decor, |
37 | } |
38 | |
39 | impl Key { |
40 | /// Create a new table key |
41 | pub fn new(key: impl Into<InternalString>) -> Self { |
42 | Self { |
43 | key: key.into(), |
44 | repr: None, |
45 | decor: Default::default(), |
46 | } |
47 | } |
48 | |
49 | /// Parse a TOML key expression |
50 | /// |
51 | /// Unlike `"".parse<Key>()`, this supports dotted keys. |
52 | pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> { |
53 | Self::try_parse_path(repr) |
54 | } |
55 | |
56 | pub(crate) fn with_repr_unchecked(mut self, repr: Repr) -> Self { |
57 | self.repr = Some(repr); |
58 | self |
59 | } |
60 | |
61 | /// While creating the `Key`, add `Decor` to it |
62 | pub fn with_decor(mut self, decor: Decor) -> Self { |
63 | self.decor = decor; |
64 | self |
65 | } |
66 | |
67 | /// Access a mutable proxy for the `Key`. |
68 | pub fn as_mut(&mut self) -> KeyMut<'_> { |
69 | KeyMut { key: self } |
70 | } |
71 | |
72 | /// Returns the parsed key value. |
73 | pub fn get(&self) -> &str { |
74 | &self.key |
75 | } |
76 | |
77 | pub(crate) fn get_internal(&self) -> &InternalString { |
78 | &self.key |
79 | } |
80 | |
81 | /// Returns key raw representation, if available. |
82 | pub fn as_repr(&self) -> Option<&Repr> { |
83 | self.repr.as_ref() |
84 | } |
85 | |
86 | /// Returns the default raw representation. |
87 | pub fn default_repr(&self) -> Repr { |
88 | to_key_repr(&self.key) |
89 | } |
90 | |
91 | /// Returns a raw representation. |
92 | pub fn display_repr(&self) -> Cow<'_, str> { |
93 | self.as_repr() |
94 | .and_then(|r| r.as_raw().as_str()) |
95 | .map(Cow::Borrowed) |
96 | .unwrap_or_else(|| { |
97 | Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned()) |
98 | }) |
99 | } |
100 | |
101 | /// Returns the surrounding whitespace |
102 | pub fn decor_mut(&mut self) -> &mut Decor { |
103 | &mut self.decor |
104 | } |
105 | |
106 | /// Returns the surrounding whitespace |
107 | pub fn decor(&self) -> &Decor { |
108 | &self.decor |
109 | } |
110 | |
111 | /// Returns the location within the original document |
112 | #[cfg (feature = "serde" )] |
113 | pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { |
114 | self.repr.as_ref().and_then(|r| r.span()) |
115 | } |
116 | |
117 | pub(crate) fn despan(&mut self, input: &str) { |
118 | self.decor.despan(input); |
119 | if let Some(repr) = &mut self.repr { |
120 | repr.despan(input) |
121 | } |
122 | } |
123 | |
124 | /// Auto formats the key. |
125 | pub fn fmt(&mut self) { |
126 | self.repr = Some(to_key_repr(&self.key)); |
127 | self.decor.clear(); |
128 | } |
129 | |
130 | fn try_parse_simple(s: &str) -> Result<Key, crate::TomlError> { |
131 | let mut key = parser::parse_key(s)?; |
132 | key.despan(s); |
133 | Ok(key) |
134 | } |
135 | |
136 | fn try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError> { |
137 | let mut keys = parser::parse_key_path(s)?; |
138 | for key in &mut keys { |
139 | key.despan(s); |
140 | } |
141 | Ok(keys) |
142 | } |
143 | } |
144 | |
145 | impl Clone for Key { |
146 | #[inline (never)] |
147 | fn clone(&self) -> Self { |
148 | Self { |
149 | key: self.key.clone(), |
150 | repr: self.repr.clone(), |
151 | decor: self.decor.clone(), |
152 | } |
153 | } |
154 | } |
155 | |
156 | impl std::ops::Deref for Key { |
157 | type Target = str; |
158 | |
159 | fn deref(&self) -> &Self::Target { |
160 | self.get() |
161 | } |
162 | } |
163 | |
164 | impl std::hash::Hash for Key { |
165 | fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
166 | self.get().hash(state); |
167 | } |
168 | } |
169 | |
170 | impl Ord for Key { |
171 | fn cmp(&self, other: &Self) -> std::cmp::Ordering { |
172 | self.get().cmp(other.get()) |
173 | } |
174 | } |
175 | |
176 | impl PartialOrd for Key { |
177 | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
178 | Some(self.cmp(other)) |
179 | } |
180 | } |
181 | |
182 | impl Eq for Key {} |
183 | |
184 | impl PartialEq for Key { |
185 | #[inline ] |
186 | fn eq(&self, other: &Key) -> bool { |
187 | PartialEq::eq(self.get(), other:other.get()) |
188 | } |
189 | } |
190 | |
191 | impl PartialEq<str> for Key { |
192 | #[inline ] |
193 | fn eq(&self, other: &str) -> bool { |
194 | PartialEq::eq(self.get(), other) |
195 | } |
196 | } |
197 | |
198 | impl<'s> PartialEq<&'s str> for Key { |
199 | #[inline ] |
200 | fn eq(&self, other: &&str) -> bool { |
201 | PartialEq::eq(self.get(), *other) |
202 | } |
203 | } |
204 | |
205 | impl PartialEq<String> for Key { |
206 | #[inline ] |
207 | fn eq(&self, other: &String) -> bool { |
208 | PartialEq::eq(self.get(), other:other.as_str()) |
209 | } |
210 | } |
211 | |
212 | impl std::fmt::Display for Key { |
213 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
214 | crate::encode::Encode::encode(self, buf:f, input:None, ("" , "" )) |
215 | } |
216 | } |
217 | |
218 | impl FromStr for Key { |
219 | type Err = crate::TomlError; |
220 | |
221 | /// Tries to parse a key from a &str, |
222 | /// if fails, tries as basic quoted key (surrounds with "") |
223 | /// and then literal quoted key (surrounds with '') |
224 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
225 | Key::try_parse_simple(s) |
226 | } |
227 | } |
228 | |
229 | fn to_key_repr(key: &str) -> Repr { |
230 | if key.as_bytes().iter().copied().all(is_unquoted_char) && !key.is_empty() { |
231 | Repr::new_unchecked(raw:key) |
232 | } else { |
233 | to_string_repr(value:key, style:Some(StringStyle::OnelineSingle), literal:Some(false)) |
234 | } |
235 | } |
236 | |
237 | impl<'b> From<&'b str> for Key { |
238 | fn from(s: &'b str) -> Self { |
239 | Key::new(key:s) |
240 | } |
241 | } |
242 | |
243 | impl<'b> From<&'b String> for Key { |
244 | fn from(s: &'b String) -> Self { |
245 | Key::new(key:s) |
246 | } |
247 | } |
248 | |
249 | impl From<String> for Key { |
250 | fn from(s: String) -> Self { |
251 | Key::new(key:s) |
252 | } |
253 | } |
254 | |
255 | impl From<InternalString> for Key { |
256 | fn from(s: InternalString) -> Self { |
257 | Key::new(key:s) |
258 | } |
259 | } |
260 | |
261 | #[doc (hidden)] |
262 | impl From<Key> for InternalString { |
263 | fn from(key: Key) -> InternalString { |
264 | key.key |
265 | } |
266 | } |
267 | |
268 | /// A mutable reference to a `Key` |
269 | #[derive (Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] |
270 | pub struct KeyMut<'k> { |
271 | key: &'k mut Key, |
272 | } |
273 | |
274 | impl<'k> KeyMut<'k> { |
275 | /// Returns the parsed key value. |
276 | pub fn get(&self) -> &str { |
277 | self.key.get() |
278 | } |
279 | |
280 | /// Returns the raw representation, if available. |
281 | pub fn as_repr(&self) -> Option<&Repr> { |
282 | self.key.as_repr() |
283 | } |
284 | |
285 | /// Returns the default raw representation. |
286 | pub fn default_repr(&self) -> Repr { |
287 | self.key.default_repr() |
288 | } |
289 | |
290 | /// Returns a raw representation. |
291 | pub fn display_repr(&self) -> Cow<str> { |
292 | self.key.display_repr() |
293 | } |
294 | |
295 | /// Returns the surrounding whitespace |
296 | pub fn decor_mut(&mut self) -> &mut Decor { |
297 | self.key.decor_mut() |
298 | } |
299 | |
300 | /// Returns the surrounding whitespace |
301 | pub fn decor(&self) -> &Decor { |
302 | self.key.decor() |
303 | } |
304 | |
305 | /// Auto formats the key. |
306 | pub fn fmt(&mut self) { |
307 | self.key.fmt() |
308 | } |
309 | } |
310 | |
311 | impl<'k> std::ops::Deref for KeyMut<'k> { |
312 | type Target = str; |
313 | |
314 | fn deref(&self) -> &Self::Target { |
315 | self.get() |
316 | } |
317 | } |
318 | |
319 | impl<'s> PartialEq<str> for KeyMut<'s> { |
320 | #[inline ] |
321 | fn eq(&self, other: &str) -> bool { |
322 | PartialEq::eq(self.get(), other) |
323 | } |
324 | } |
325 | |
326 | impl<'s> PartialEq<&'s str> for KeyMut<'s> { |
327 | #[inline ] |
328 | fn eq(&self, other: &&str) -> bool { |
329 | PartialEq::eq(self.get(), *other) |
330 | } |
331 | } |
332 | |
333 | impl<'s> PartialEq<String> for KeyMut<'s> { |
334 | #[inline ] |
335 | fn eq(&self, other: &String) -> bool { |
336 | PartialEq::eq(self.get(), other:other.as_str()) |
337 | } |
338 | } |
339 | |
340 | impl<'k> std::fmt::Display for KeyMut<'k> { |
341 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
342 | std::fmt::Display::fmt(&self.key, f) |
343 | } |
344 | } |
345 | |