1use std::borrow::Cow;
2use std::str::FromStr;
3
4use crate::encode::{to_string_repr, StringStyle};
5use crate::parser;
6use crate::parser::key::is_unquoted_char;
7use crate::repr::{Decor, Repr};
8use 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)]
33pub struct Key {
34 key: InternalString,
35 pub(crate) repr: Option<Repr>,
36 pub(crate) decor: Decor,
37}
38
39impl 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
145impl 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
156impl std::ops::Deref for Key {
157 type Target = str;
158
159 fn deref(&self) -> &Self::Target {
160 self.get()
161 }
162}
163
164impl std::hash::Hash for Key {
165 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
166 self.get().hash(state);
167 }
168}
169
170impl Ord for Key {
171 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
172 self.get().cmp(other.get())
173 }
174}
175
176impl PartialOrd for Key {
177 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
178 Some(self.cmp(other))
179 }
180}
181
182impl Eq for Key {}
183
184impl PartialEq for Key {
185 #[inline]
186 fn eq(&self, other: &Key) -> bool {
187 PartialEq::eq(self.get(), other:other.get())
188 }
189}
190
191impl PartialEq<str> for Key {
192 #[inline]
193 fn eq(&self, other: &str) -> bool {
194 PartialEq::eq(self.get(), other)
195 }
196}
197
198impl<'s> PartialEq<&'s str> for Key {
199 #[inline]
200 fn eq(&self, other: &&str) -> bool {
201 PartialEq::eq(self.get(), *other)
202 }
203}
204
205impl 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
212impl 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
218impl 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
229fn 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
237impl<'b> From<&'b str> for Key {
238 fn from(s: &'b str) -> Self {
239 Key::new(key:s)
240 }
241}
242
243impl<'b> From<&'b String> for Key {
244 fn from(s: &'b String) -> Self {
245 Key::new(key:s)
246 }
247}
248
249impl From<String> for Key {
250 fn from(s: String) -> Self {
251 Key::new(key:s)
252 }
253}
254
255impl From<InternalString> for Key {
256 fn from(s: InternalString) -> Self {
257 Key::new(key:s)
258 }
259}
260
261#[doc(hidden)]
262impl 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)]
270pub struct KeyMut<'k> {
271 key: &'k mut Key,
272}
273
274impl<'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
311impl<'k> std::ops::Deref for KeyMut<'k> {
312 type Target = str;
313
314 fn deref(&self) -> &Self::Target {
315 self.get()
316 }
317}
318
319impl<'s> PartialEq<str> for KeyMut<'s> {
320 #[inline]
321 fn eq(&self, other: &str) -> bool {
322 PartialEq::eq(self.get(), other)
323 }
324}
325
326impl<'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
333impl<'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
340impl<'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