1 use std::borrow::Cow;
2 use std::str::FromStr;
3
4 use crate::repr::{Decor, Repr};
5 use crate::InternalString;
6
7 /// Key as part of a Key/Value Pair or a table header.
8 ///
9 /// # Examples
10 ///
11 /// ```notrust
12 /// [dependencies."nom"]
13 /// version = "5.0"
14 /// 'literal key' = "nonsense"
15 /// "basic string key" = 42
16 /// ```
17 ///
18 /// There are 3 types of keys:
19 ///
20 /// 1. Bare keys (`version` and `dependencies`)
21 ///
22 /// 2. Basic quoted keys (`"basic string key"` and `"nom"`)
23 ///
24 /// 3. Literal quoted keys (`'literal key'`)
25 ///
26 /// For details see [toml spec](https://github.com/toml-lang/toml/#keyvalue-pair).
27 ///
28 /// To parse a key use `FromStr` trait implementation: `"string".parse::<Key>()`.
29 #[derive(Debug)]
30 pub struct Key {
31 key: InternalString,
32 pub(crate) repr: Option<Repr>,
33 pub(crate) leaf_decor: Decor,
34 pub(crate) dotted_decor: Decor,
35 }
36
37 impl Key {
38 /// Create a new table key
new(key: impl Into<InternalString>) -> Self39 pub fn new(key: impl Into<InternalString>) -> Self {
40 Self {
41 key: key.into(),
42 repr: None,
43 leaf_decor: Default::default(),
44 dotted_decor: Default::default(),
45 }
46 }
47
48 /// Parse a TOML key expression
49 ///
50 /// Unlike `"".parse<Key>()`, this supports dotted keys.
51 #[cfg(feature = "parse")]
parse(repr: &str) -> Result<Vec<Self>, crate::TomlError>52 pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> {
53 Self::try_parse_path(repr)
54 }
55
with_repr_unchecked(mut self, repr: Repr) -> Self56 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 #[deprecated(since = "0.21.1", note = "Replaced with `with_leaf_decor`")]
with_decor(self, decor: Decor) -> Self63 pub fn with_decor(self, decor: Decor) -> Self {
64 self.with_leaf_decor(decor)
65 }
66
67 /// While creating the `Key`, add `Decor` to it for the line entry
with_leaf_decor(mut self, decor: Decor) -> Self68 pub fn with_leaf_decor(mut self, decor: Decor) -> Self {
69 self.leaf_decor = decor;
70 self
71 }
72
73 /// While creating the `Key`, add `Decor` to it for between dots
with_dotted_decor(mut self, decor: Decor) -> Self74 pub fn with_dotted_decor(mut self, decor: Decor) -> Self {
75 self.dotted_decor = decor;
76 self
77 }
78
79 /// Access a mutable proxy for the `Key`.
as_mut(&mut self) -> KeyMut<'_>80 pub fn as_mut(&mut self) -> KeyMut<'_> {
81 KeyMut { key: self }
82 }
83
84 /// Returns the parsed key value.
get(&self) -> &str85 pub fn get(&self) -> &str {
86 &self.key
87 }
88
get_internal(&self) -> &InternalString89 pub(crate) fn get_internal(&self) -> &InternalString {
90 &self.key
91 }
92
93 /// Returns key raw representation, if available.
as_repr(&self) -> Option<&Repr>94 pub fn as_repr(&self) -> Option<&Repr> {
95 self.repr.as_ref()
96 }
97
98 /// Returns the default raw representation.
99 #[cfg(feature = "display")]
default_repr(&self) -> Repr100 pub fn default_repr(&self) -> Repr {
101 to_key_repr(&self.key)
102 }
103
104 /// Returns a raw representation.
105 #[cfg(feature = "display")]
display_repr(&self) -> Cow<'_, str>106 pub fn display_repr(&self) -> Cow<'_, str> {
107 self.as_repr()
108 .and_then(|r| r.as_raw().as_str())
109 .map(Cow::Borrowed)
110 .unwrap_or_else(|| {
111 Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned())
112 })
113 }
114
115 /// Returns the surrounding whitespace
116 #[deprecated(since = "0.21.1", note = "Replaced with `decor_mut`")]
decor_mut(&mut self) -> &mut Decor117 pub fn decor_mut(&mut self) -> &mut Decor {
118 self.leaf_decor_mut()
119 }
120
121 /// Returns the surrounding whitespace for the line entry
leaf_decor_mut(&mut self) -> &mut Decor122 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
123 &mut self.leaf_decor
124 }
125
126 /// Returns the surrounding whitespace for between dots
dotted_decor_mut(&mut self) -> &mut Decor127 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
128 &mut self.dotted_decor
129 }
130
131 /// Returns the surrounding whitespace
132 #[deprecated(since = "0.21.1", note = "Replaced with `decor`")]
decor(&self) -> &Decor133 pub fn decor(&self) -> &Decor {
134 self.leaf_decor()
135 }
136
137 /// Returns the surrounding whitespace for the line entry
leaf_decor(&self) -> &Decor138 pub fn leaf_decor(&self) -> &Decor {
139 &self.leaf_decor
140 }
141
142 /// Returns the surrounding whitespace for between dots
dotted_decor(&self) -> &Decor143 pub fn dotted_decor(&self) -> &Decor {
144 &self.dotted_decor
145 }
146
147 /// Returns the location within the original document
148 #[cfg(feature = "serde")]
span(&self) -> Option<std::ops::Range<usize>>149 pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> {
150 self.repr.as_ref().and_then(|r| r.span())
151 }
152
despan(&mut self, input: &str)153 pub(crate) fn despan(&mut self, input: &str) {
154 self.leaf_decor.despan(input);
155 self.dotted_decor.despan(input);
156 if let Some(repr) = &mut self.repr {
157 repr.despan(input)
158 }
159 }
160
161 /// Auto formats the key.
fmt(&mut self)162 pub fn fmt(&mut self) {
163 self.repr = None;
164 self.leaf_decor.clear();
165 self.dotted_decor.clear();
166 }
167
168 #[cfg(feature = "parse")]
try_parse_simple(s: &str) -> Result<Key, crate::TomlError>169 fn try_parse_simple(s: &str) -> Result<Key, crate::TomlError> {
170 let mut key = crate::parser::parse_key(s)?;
171 key.despan(s);
172 Ok(key)
173 }
174
175 #[cfg(feature = "parse")]
try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError>176 fn try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError> {
177 let mut keys = crate::parser::parse_key_path(s)?;
178 for key in &mut keys {
179 key.despan(s);
180 }
181 Ok(keys)
182 }
183 }
184
185 impl Clone for Key {
186 #[inline(never)]
clone(&self) -> Self187 fn clone(&self) -> Self {
188 Self {
189 key: self.key.clone(),
190 repr: self.repr.clone(),
191 leaf_decor: self.leaf_decor.clone(),
192 dotted_decor: self.dotted_decor.clone(),
193 }
194 }
195 }
196
197 impl std::ops::Deref for Key {
198 type Target = str;
199
deref(&self) -> &Self::Target200 fn deref(&self) -> &Self::Target {
201 self.get()
202 }
203 }
204
205 impl std::hash::Hash for Key {
hash<H: std::hash::Hasher>(&self, state: &mut H)206 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
207 self.get().hash(state);
208 }
209 }
210
211 impl Ord for Key {
cmp(&self, other: &Self) -> std::cmp::Ordering212 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
213 self.get().cmp(other.get())
214 }
215 }
216
217 impl PartialOrd for Key {
partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>218 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
219 Some(self.cmp(other))
220 }
221 }
222
223 impl Eq for Key {}
224
225 impl PartialEq for Key {
226 #[inline]
eq(&self, other: &Key) -> bool227 fn eq(&self, other: &Key) -> bool {
228 PartialEq::eq(self.get(), other.get())
229 }
230 }
231
232 impl PartialEq<str> for Key {
233 #[inline]
eq(&self, other: &str) -> bool234 fn eq(&self, other: &str) -> bool {
235 PartialEq::eq(self.get(), other)
236 }
237 }
238
239 impl<'s> PartialEq<&'s str> for Key {
240 #[inline]
eq(&self, other: &&str) -> bool241 fn eq(&self, other: &&str) -> bool {
242 PartialEq::eq(self.get(), *other)
243 }
244 }
245
246 impl PartialEq<String> for Key {
247 #[inline]
eq(&self, other: &String) -> bool248 fn eq(&self, other: &String) -> bool {
249 PartialEq::eq(self.get(), other.as_str())
250 }
251 }
252
253 #[cfg(feature = "display")]
254 impl std::fmt::Display for Key {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 crate::encode::encode_key(self, f, None)
257 }
258 }
259
260 #[cfg(feature = "parse")]
261 impl FromStr for Key {
262 type Err = crate::TomlError;
263
264 /// Tries to parse a key from a &str,
265 /// if fails, tries as basic quoted key (surrounds with "")
266 /// and then literal quoted key (surrounds with '')
from_str(s: &str) -> Result<Self, Self::Err>267 fn from_str(s: &str) -> Result<Self, Self::Err> {
268 Key::try_parse_simple(s)
269 }
270 }
271
272 #[cfg(feature = "display")]
to_key_repr(key: &str) -> Repr273 fn to_key_repr(key: &str) -> Repr {
274 #[cfg(feature = "parse")]
275 {
276 if key
277 .as_bytes()
278 .iter()
279 .copied()
280 .all(crate::parser::key::is_unquoted_char)
281 && !key.is_empty()
282 {
283 Repr::new_unchecked(key)
284 } else {
285 crate::encode::to_string_repr(
286 key,
287 Some(crate::encode::StringStyle::OnelineSingle),
288 Some(false),
289 )
290 }
291 }
292 #[cfg(not(feature = "parse"))]
293 {
294 crate::encode::to_string_repr(
295 key,
296 Some(crate::encode::StringStyle::OnelineSingle),
297 Some(false),
298 )
299 }
300 }
301
302 impl<'b> From<&'b str> for Key {
from(s: &'b str) -> Self303 fn from(s: &'b str) -> Self {
304 Key::new(s)
305 }
306 }
307
308 impl<'b> From<&'b String> for Key {
from(s: &'b String) -> Self309 fn from(s: &'b String) -> Self {
310 Key::new(s)
311 }
312 }
313
314 impl From<String> for Key {
from(s: String) -> Self315 fn from(s: String) -> Self {
316 Key::new(s)
317 }
318 }
319
320 impl From<InternalString> for Key {
from(s: InternalString) -> Self321 fn from(s: InternalString) -> Self {
322 Key::new(s)
323 }
324 }
325
326 #[doc(hidden)]
327 impl From<Key> for InternalString {
from(key: Key) -> InternalString328 fn from(key: Key) -> InternalString {
329 key.key
330 }
331 }
332
333 /// A mutable reference to a `Key`'s formatting
334 #[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
335 pub struct KeyMut<'k> {
336 key: &'k mut Key,
337 }
338
339 impl<'k> KeyMut<'k> {
340 /// Returns the parsed key value.
get(&self) -> &str341 pub fn get(&self) -> &str {
342 self.key.get()
343 }
344
345 /// Returns the raw representation, if available.
as_repr(&self) -> Option<&Repr>346 pub fn as_repr(&self) -> Option<&Repr> {
347 self.key.as_repr()
348 }
349
350 /// Returns the default raw representation.
351 #[cfg(feature = "display")]
default_repr(&self) -> Repr352 pub fn default_repr(&self) -> Repr {
353 self.key.default_repr()
354 }
355
356 /// Returns a raw representation.
357 #[cfg(feature = "display")]
display_repr(&self) -> Cow<str>358 pub fn display_repr(&self) -> Cow<str> {
359 self.key.display_repr()
360 }
361
362 /// Returns the surrounding whitespace
363 #[deprecated(since = "0.21.1", note = "Replaced with `decor_mut`")]
decor_mut(&mut self) -> &mut Decor364 pub fn decor_mut(&mut self) -> &mut Decor {
365 #![allow(deprecated)]
366 self.key.decor_mut()
367 }
368
369 /// Returns the surrounding whitespace for the line entry
leaf_decor_mut(&mut self) -> &mut Decor370 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
371 self.key.leaf_decor_mut()
372 }
373
374 /// Returns the surrounding whitespace for between dots
dotted_decor_mut(&mut self) -> &mut Decor375 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
376 self.key.dotted_decor_mut()
377 }
378
379 /// Returns the surrounding whitespace
380 #[deprecated(since = "0.21.1", note = "Replaced with `decor`")]
decor(&self) -> &Decor381 pub fn decor(&self) -> &Decor {
382 #![allow(deprecated)]
383 self.key.decor()
384 }
385
386 /// Returns the surrounding whitespace for the line entry
leaf_decor(&self) -> &Decor387 pub fn leaf_decor(&self) -> &Decor {
388 self.key.leaf_decor()
389 }
390
391 /// Returns the surrounding whitespace for between dots
dotted_decor(&self) -> &Decor392 pub fn dotted_decor(&self) -> &Decor {
393 self.key.dotted_decor()
394 }
395
396 /// Auto formats the key.
fmt(&mut self)397 pub fn fmt(&mut self) {
398 self.key.fmt()
399 }
400 }
401
402 impl<'k> std::ops::Deref for KeyMut<'k> {
403 type Target = str;
404
deref(&self) -> &Self::Target405 fn deref(&self) -> &Self::Target {
406 self.get()
407 }
408 }
409
410 impl<'s> PartialEq<str> for KeyMut<'s> {
411 #[inline]
eq(&self, other: &str) -> bool412 fn eq(&self, other: &str) -> bool {
413 PartialEq::eq(self.get(), other)
414 }
415 }
416
417 impl<'s> PartialEq<&'s str> for KeyMut<'s> {
418 #[inline]
eq(&self, other: &&str) -> bool419 fn eq(&self, other: &&str) -> bool {
420 PartialEq::eq(self.get(), *other)
421 }
422 }
423
424 impl<'s> PartialEq<String> for KeyMut<'s> {
425 #[inline]
eq(&self, other: &String) -> bool426 fn eq(&self, other: &String) -> bool {
427 PartialEq::eq(self.get(), other.as_str())
428 }
429 }
430
431 #[cfg(feature = "display")]
432 impl<'k> std::fmt::Display for KeyMut<'k> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result433 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
434 std::fmt::Display::fmt(&self.key, f)
435 }
436 }
437