1use std::borrow::Cow;
2use std::str::FromStr;
3
4#[cfg(feature = "display")]
5use toml_write::ToTomlKey as _;
6
7use crate::repr::{Decor, Repr};
8use crate::InternalString;
9
10#[derive(Debug)]
34pub struct Key {
35 key: InternalString,
36 pub(crate) repr: Option<Repr>,
37 pub(crate) leaf_decor: Decor,
38 pub(crate) dotted_decor: Decor,
39}
40
41impl Key {
42 pub fn new(key: impl Into<InternalString>) -> Self {
44 Self {
45 key: key.into(),
46 repr: None,
47 leaf_decor: Default::default(),
48 dotted_decor: Default::default(),
49 }
50 }
51
52 #[cfg(feature = "parse")]
56 pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> {
57 Self::try_parse_path(repr)
58 }
59
60 pub(crate) fn with_repr_unchecked(mut self, repr: Repr) -> Self {
61 self.repr = Some(repr);
62 self
63 }
64
65 #[deprecated(since = "0.21.1", note = "Replaced with `with_leaf_decor`")]
67 pub fn with_decor(self, decor: Decor) -> Self {
68 self.with_leaf_decor(decor)
69 }
70
71 pub fn with_leaf_decor(mut self, decor: Decor) -> Self {
73 self.leaf_decor = decor;
74 self
75 }
76
77 pub fn with_dotted_decor(mut self, decor: Decor) -> Self {
79 self.dotted_decor = decor;
80 self
81 }
82
83 pub fn as_mut(&mut self) -> KeyMut<'_> {
85 KeyMut { key: self }
86 }
87
88 pub fn get(&self) -> &str {
90 &self.key
91 }
92
93 pub fn as_repr(&self) -> Option<&Repr> {
95 self.repr.as_ref()
96 }
97
98 #[cfg(feature = "display")]
100 pub fn default_repr(&self) -> Repr {
101 let output = toml_write::TomlKeyBuilder::new(&self.key)
102 .as_default()
103 .to_toml_key();
104 Repr::new_unchecked(output)
105 }
106
107 #[cfg(feature = "display")]
109 pub fn display_repr(&self) -> Cow<'_, str> {
110 self.as_repr()
111 .and_then(|r| r.as_raw().as_str())
112 .map(Cow::Borrowed)
113 .unwrap_or_else(|| {
114 Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned())
115 })
116 }
117
118 #[deprecated(
120 since = "0.21.1",
121 note = "Replaced with `dotted_decor_mut`, `leaf_decor_mut"
122 )]
123 pub fn decor_mut(&mut self) -> &mut Decor {
124 self.leaf_decor_mut()
125 }
126
127 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
129 &mut self.leaf_decor
130 }
131
132 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
134 &mut self.dotted_decor
135 }
136
137 #[deprecated(since = "0.21.1", note = "Replaced with `dotted_decor`, `leaf_decor")]
139 pub fn decor(&self) -> &Decor {
140 self.leaf_decor()
141 }
142
143 pub fn leaf_decor(&self) -> &Decor {
145 &self.leaf_decor
146 }
147
148 pub fn dotted_decor(&self) -> &Decor {
150 &self.dotted_decor
151 }
152
153 pub fn span(&self) -> Option<std::ops::Range<usize>> {
157 self.repr.as_ref().and_then(|r| r.span())
158 }
159
160 pub(crate) fn despan(&mut self, input: &str) {
161 self.leaf_decor.despan(input);
162 self.dotted_decor.despan(input);
163 if let Some(repr) = &mut self.repr {
164 repr.despan(input);
165 }
166 }
167
168 pub fn fmt(&mut self) {
170 self.repr = None;
171 self.leaf_decor.clear();
172 self.dotted_decor.clear();
173 }
174
175 #[cfg(feature = "parse")]
176 fn try_parse_simple(s: &str) -> Result<Key, crate::TomlError> {
177 let mut key = crate::parser::parse_key(s)?;
178 key.despan(s);
179 Ok(key)
180 }
181
182 #[cfg(feature = "parse")]
183 fn try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError> {
184 let mut keys = crate::parser::parse_key_path(s)?;
185 for key in &mut keys {
186 key.despan(s);
187 }
188 Ok(keys)
189 }
190}
191
192impl Clone for Key {
193 #[inline(never)]
194 fn clone(&self) -> Self {
195 Self {
196 key: self.key.clone(),
197 repr: self.repr.clone(),
198 leaf_decor: self.leaf_decor.clone(),
199 dotted_decor: self.dotted_decor.clone(),
200 }
201 }
202}
203
204impl std::ops::Deref for Key {
205 type Target = str;
206
207 fn deref(&self) -> &Self::Target {
208 self.get()
209 }
210}
211
212impl std::borrow::Borrow<str> for Key {
213 #[inline]
214 fn borrow(&self) -> &str {
215 self.get()
216 }
217}
218
219impl std::hash::Hash for Key {
220 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
221 self.get().hash(state);
222 }
223}
224
225impl Ord for Key {
226 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
227 self.get().cmp(other.get())
228 }
229}
230
231impl PartialOrd for Key {
232 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
233 Some(self.cmp(other))
234 }
235}
236
237impl Eq for Key {}
238
239impl PartialEq for Key {
240 #[inline]
241 fn eq(&self, other: &Key) -> bool {
242 PartialEq::eq(self.get(), other.get())
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<&str> for Key {
254 #[inline]
255 fn eq(&self, other: &&str) -> bool {
256 PartialEq::eq(self.get(), *other)
257 }
258}
259
260impl PartialEq<String> for Key {
261 #[inline]
262 fn eq(&self, other: &String) -> bool {
263 PartialEq::eq(self.get(), other.as_str())
264 }
265}
266
267#[cfg(feature = "display")]
268impl std::fmt::Display for Key {
269 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
270 crate::encode::encode_key(self, f, None)
271 }
272}
273
274#[cfg(feature = "parse")]
275impl FromStr for Key {
276 type Err = crate::TomlError;
277
278 fn from_str(s: &str) -> Result<Self, Self::Err> {
282 Key::try_parse_simple(s)
283 }
284}
285
286impl<'b> From<&'b str> for Key {
287 fn from(s: &'b str) -> Self {
288 Key::new(s)
289 }
290}
291
292impl<'b> From<&'b String> for Key {
293 fn from(s: &'b String) -> Self {
294 Key::new(s)
295 }
296}
297
298impl From<String> for Key {
299 fn from(s: String) -> Self {
300 Key::new(s)
301 }
302}
303
304impl From<InternalString> for Key {
305 fn from(s: InternalString) -> Self {
306 Key::new(s)
307 }
308}
309
310#[doc(hidden)]
311impl From<Key> for InternalString {
312 fn from(key: Key) -> InternalString {
313 key.key
314 }
315}
316
317#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
319pub struct KeyMut<'k> {
320 key: &'k mut Key,
321}
322
323impl KeyMut<'_> {
324 pub fn get(&self) -> &str {
326 self.key.get()
327 }
328
329 pub fn as_repr(&self) -> Option<&Repr> {
331 self.key.as_repr()
332 }
333
334 #[cfg(feature = "display")]
336 pub fn default_repr(&self) -> Repr {
337 self.key.default_repr()
338 }
339
340 #[cfg(feature = "display")]
342 pub fn display_repr(&self) -> Cow<'_, str> {
343 self.key.display_repr()
344 }
345
346 #[deprecated(
348 since = "0.21.1",
349 note = "Replaced with `dotted_decor_mut`, `leaf_decor_mut"
350 )]
351 pub fn decor_mut(&mut self) -> &mut Decor {
352 #![allow(deprecated)]
353 self.key.decor_mut()
354 }
355
356 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
358 self.key.leaf_decor_mut()
359 }
360
361 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
363 self.key.dotted_decor_mut()
364 }
365
366 #[deprecated(since = "0.21.1", note = "Replaced with `dotted_decor`, `leaf_decor")]
368 pub fn decor(&self) -> &Decor {
369 #![allow(deprecated)]
370 self.key.decor()
371 }
372
373 pub fn leaf_decor(&self) -> &Decor {
375 self.key.leaf_decor()
376 }
377
378 pub fn dotted_decor(&self) -> &Decor {
380 self.key.dotted_decor()
381 }
382
383 pub fn fmt(&mut self) {
385 self.key.fmt();
386 }
387}
388
389impl std::ops::Deref for KeyMut<'_> {
390 type Target = str;
391
392 fn deref(&self) -> &Self::Target {
393 self.get()
394 }
395}
396
397impl PartialEq<str> for KeyMut<'_> {
398 #[inline]
399 fn eq(&self, other: &str) -> bool {
400 PartialEq::eq(self.get(), other)
401 }
402}
403
404impl<'s> PartialEq<&'s str> for KeyMut<'s> {
405 #[inline]
406 fn eq(&self, other: &&str) -> bool {
407 PartialEq::eq(self.get(), *other)
408 }
409}
410
411impl PartialEq<String> for KeyMut<'_> {
412 #[inline]
413 fn eq(&self, other: &String) -> bool {
414 PartialEq::eq(self.get(), other.as_str())
415 }
416}
417
418#[cfg(feature = "display")]
419impl std::fmt::Display for KeyMut<'_> {
420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421 std::fmt::Display::fmt(&self.key, f)
422 }
423}
424
425#[test]
426#[cfg(feature = "parse")]
427#[cfg(feature = "display")]
428fn string_roundtrip() {
429 Key::new("hello").to_string().parse::<Key>().unwrap();
430}