1use std::borrow::Cow;
2use std::str::FromStr;
3
4use crate::repr::{Decor, Repr};
5use crate::InternalString;
6
7#[derive(Debug)]
30pub 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
37impl Key {
38 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 #[cfg(feature = "parse")]
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 #[deprecated(since = "0.21.1", note = "Replaced with `with_leaf_decor`")]
63 pub fn with_decor(self, decor: Decor) -> Self {
64 self.with_leaf_decor(decor)
65 }
66
67 pub fn with_leaf_decor(mut self, decor: Decor) -> Self {
69 self.leaf_decor = decor;
70 self
71 }
72
73 pub fn with_dotted_decor(mut self, decor: Decor) -> Self {
75 self.dotted_decor = decor;
76 self
77 }
78
79 pub fn as_mut(&mut self) -> KeyMut<'_> {
81 KeyMut { key: self }
82 }
83
84 pub fn get(&self) -> &str {
86 &self.key
87 }
88
89 pub fn as_repr(&self) -> Option<&Repr> {
91 self.repr.as_ref()
92 }
93
94 #[cfg(feature = "display")]
96 pub fn default_repr(&self) -> Repr {
97 to_key_repr(&self.key)
98 }
99
100 #[cfg(feature = "display")]
102 pub fn display_repr(&self) -> Cow<'_, str> {
103 self.as_repr()
104 .and_then(|r| r.as_raw().as_str())
105 .map(Cow::Borrowed)
106 .unwrap_or_else(|| {
107 Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned())
108 })
109 }
110
111 #[deprecated(
113 since = "0.21.1",
114 note = "Replaced with `dotted_decor_mut`, `leaf_decor_mut"
115 )]
116 pub fn decor_mut(&mut self) -> &mut Decor {
117 self.leaf_decor_mut()
118 }
119
120 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
122 &mut self.leaf_decor
123 }
124
125 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
127 &mut self.dotted_decor
128 }
129
130 #[deprecated(since = "0.21.1", note = "Replaced with `dotted_decor`, `leaf_decor")]
132 pub fn decor(&self) -> &Decor {
133 self.leaf_decor()
134 }
135
136 pub fn leaf_decor(&self) -> &Decor {
138 &self.leaf_decor
139 }
140
141 pub fn dotted_decor(&self) -> &Decor {
143 &self.dotted_decor
144 }
145
146 pub fn span(&self) -> Option<std::ops::Range<usize>> {
150 self.repr.as_ref().and_then(|r| r.span())
151 }
152
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 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")]
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")]
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
185impl Clone for Key {
186 #[inline(never)]
187 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
197impl std::ops::Deref for Key {
198 type Target = str;
199
200 fn deref(&self) -> &Self::Target {
201 self.get()
202 }
203}
204
205impl std::borrow::Borrow<str> for Key {
206 #[inline]
207 fn borrow(&self) -> &str {
208 self.get()
209 }
210}
211
212impl std::hash::Hash for Key {
213 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
214 self.get().hash(state);
215 }
216}
217
218impl Ord for Key {
219 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
220 self.get().cmp(other.get())
221 }
222}
223
224impl PartialOrd for Key {
225 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
226 Some(self.cmp(other))
227 }
228}
229
230impl Eq for Key {}
231
232impl PartialEq for Key {
233 #[inline]
234 fn eq(&self, other: &Key) -> bool {
235 PartialEq::eq(self.get(), other.get())
236 }
237}
238
239impl PartialEq<str> for Key {
240 #[inline]
241 fn eq(&self, other: &str) -> bool {
242 PartialEq::eq(self.get(), other)
243 }
244}
245
246impl PartialEq<&str> for Key {
247 #[inline]
248 fn eq(&self, other: &&str) -> bool {
249 PartialEq::eq(self.get(), *other)
250 }
251}
252
253impl PartialEq<String> for Key {
254 #[inline]
255 fn eq(&self, other: &String) -> bool {
256 PartialEq::eq(self.get(), other.as_str())
257 }
258}
259
260#[cfg(feature = "display")]
261impl std::fmt::Display for Key {
262 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
263 crate::encode::encode_key(self, f, None)
264 }
265}
266
267#[cfg(feature = "parse")]
268impl FromStr for Key {
269 type Err = crate::TomlError;
270
271 fn from_str(s: &str) -> Result<Self, Self::Err> {
275 Key::try_parse_simple(s)
276 }
277}
278
279#[cfg(feature = "display")]
280fn to_key_repr(key: &str) -> Repr {
281 #[cfg(feature = "parse")]
282 {
283 if key
284 .as_bytes()
285 .iter()
286 .copied()
287 .all(crate::parser::key::is_unquoted_char)
288 && !key.is_empty()
289 {
290 Repr::new_unchecked(key)
291 } else {
292 crate::encode::to_string_repr(
293 key,
294 Some(crate::encode::StringStyle::OnelineSingle),
295 None,
296 )
297 }
298 }
299 #[cfg(not(feature = "parse"))]
300 {
301 crate::encode::to_string_repr(key, Some(crate::encode::StringStyle::OnelineSingle), None)
302 }
303}
304
305impl<'b> From<&'b str> for Key {
306 fn from(s: &'b str) -> Self {
307 Key::new(s)
308 }
309}
310
311impl<'b> From<&'b String> for Key {
312 fn from(s: &'b String) -> Self {
313 Key::new(s)
314 }
315}
316
317impl From<String> for Key {
318 fn from(s: String) -> Self {
319 Key::new(s)
320 }
321}
322
323impl From<InternalString> for Key {
324 fn from(s: InternalString) -> Self {
325 Key::new(s)
326 }
327}
328
329#[doc(hidden)]
330impl From<Key> for InternalString {
331 fn from(key: Key) -> InternalString {
332 key.key
333 }
334}
335
336#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
338pub struct KeyMut<'k> {
339 key: &'k mut Key,
340}
341
342impl KeyMut<'_> {
343 pub fn get(&self) -> &str {
345 self.key.get()
346 }
347
348 pub fn as_repr(&self) -> Option<&Repr> {
350 self.key.as_repr()
351 }
352
353 #[cfg(feature = "display")]
355 pub fn default_repr(&self) -> Repr {
356 self.key.default_repr()
357 }
358
359 #[cfg(feature = "display")]
361 pub fn display_repr(&self) -> Cow<'_, str> {
362 self.key.display_repr()
363 }
364
365 #[deprecated(
367 since = "0.21.1",
368 note = "Replaced with `dotted_decor_mut`, `leaf_decor_mut"
369 )]
370 pub fn decor_mut(&mut self) -> &mut Decor {
371 #![allow(deprecated)]
372 self.key.decor_mut()
373 }
374
375 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
377 self.key.leaf_decor_mut()
378 }
379
380 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
382 self.key.dotted_decor_mut()
383 }
384
385 #[deprecated(since = "0.21.1", note = "Replaced with `dotted_decor`, `leaf_decor")]
387 pub fn decor(&self) -> &Decor {
388 #![allow(deprecated)]
389 self.key.decor()
390 }
391
392 pub fn leaf_decor(&self) -> &Decor {
394 self.key.leaf_decor()
395 }
396
397 pub fn dotted_decor(&self) -> &Decor {
399 self.key.dotted_decor()
400 }
401
402 pub fn fmt(&mut self) {
404 self.key.fmt();
405 }
406}
407
408impl std::ops::Deref for KeyMut<'_> {
409 type Target = str;
410
411 fn deref(&self) -> &Self::Target {
412 self.get()
413 }
414}
415
416impl PartialEq<str> for KeyMut<'_> {
417 #[inline]
418 fn eq(&self, other: &str) -> bool {
419 PartialEq::eq(self.get(), other)
420 }
421}
422
423impl<'s> PartialEq<&'s str> for KeyMut<'s> {
424 #[inline]
425 fn eq(&self, other: &&str) -> bool {
426 PartialEq::eq(self.get(), *other)
427 }
428}
429
430impl PartialEq<String> for KeyMut<'_> {
431 #[inline]
432 fn eq(&self, other: &String) -> bool {
433 PartialEq::eq(self.get(), other.as_str())
434 }
435}
436
437#[cfg(feature = "display")]
438impl std::fmt::Display for KeyMut<'_> {
439 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
440 std::fmt::Display::fmt(&self.key, f)
441 }
442}
443
444#[test]
445#[cfg(feature = "parse")]
446#[cfg(feature = "display")]
447fn string_roundtrip() {
448 Key::new("hello").to_string().parse::<Key>().unwrap();
449}