1use std::borrow::Cow;
2use std::str::FromStr;
3
4#[cfg(feature = "display")]
5use toml_writer::ToTomlKey as _;
6
7use crate::repr::{Decor, Repr};
8
9#[derive(Debug)]
33pub struct Key {
34 key: String,
35 pub(crate) repr: Option<Repr>,
36 pub(crate) leaf_decor: Decor,
37 pub(crate) dotted_decor: Decor,
38}
39
40impl Key {
41 pub fn new(key: impl Into<String>) -> Self {
43 Self {
44 key: key.into(),
45 repr: None,
46 leaf_decor: Default::default(),
47 dotted_decor: Default::default(),
48 }
49 }
50
51 #[cfg(feature = "parse")]
55 pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> {
56 Self::try_parse_path(repr)
57 }
58
59 pub(crate) fn with_repr_unchecked(mut self, repr: Repr) -> Self {
60 self.repr = Some(repr);
61 self
62 }
63
64 pub fn with_leaf_decor(mut self, decor: Decor) -> Self {
66 self.leaf_decor = decor;
67 self
68 }
69
70 pub fn with_dotted_decor(mut self, decor: Decor) -> Self {
72 self.dotted_decor = decor;
73 self
74 }
75
76 pub fn as_mut(&mut self) -> KeyMut<'_> {
78 KeyMut { key: self }
79 }
80
81 pub fn get(&self) -> &str {
83 &self.key
84 }
85
86 pub fn as_repr(&self) -> Option<&Repr> {
88 self.repr.as_ref()
89 }
90
91 #[cfg(feature = "display")]
93 pub fn default_repr(&self) -> Repr {
94 let output = toml_writer::TomlKeyBuilder::new(&self.key)
95 .as_default()
96 .to_toml_key();
97 Repr::new_unchecked(output)
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 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
113 &mut self.leaf_decor
114 }
115
116 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
118 &mut self.dotted_decor
119 }
120
121 pub fn leaf_decor(&self) -> &Decor {
123 &self.leaf_decor
124 }
125
126 pub fn dotted_decor(&self) -> &Decor {
128 &self.dotted_decor
129 }
130
131 pub fn span(&self) -> Option<std::ops::Range<usize>> {
135 self.repr.as_ref().and_then(|r| r.span())
136 }
137
138 pub(crate) fn despan(&mut self, input: &str) {
139 self.leaf_decor.despan(input);
140 self.dotted_decor.despan(input);
141 if let Some(repr) = &mut self.repr {
142 repr.despan(input);
143 }
144 }
145
146 pub fn fmt(&mut self) {
148 self.repr = None;
149 self.leaf_decor.clear();
150 self.dotted_decor.clear();
151 }
152
153 #[cfg(feature = "parse")]
154 fn try_parse_simple(s: &str) -> Result<Self, crate::TomlError> {
155 let source = toml_parser::Source::new(s);
156 let mut sink = crate::error::TomlSink::<Option<_>>::new(source);
157 let mut key = crate::parser::parse_key(source, &mut sink);
158 if let Some(err) = sink.into_inner() {
159 Err(err)
160 } else {
161 key.despan(s);
162 Ok(key)
163 }
164 }
165
166 #[cfg(feature = "parse")]
167 fn try_parse_path(s: &str) -> Result<Vec<Self>, crate::TomlError> {
168 let source = toml_parser::Source::new(s);
169 let mut sink = crate::error::TomlSink::<Option<_>>::new(source);
170 let mut keys = crate::parser::parse_key_path(source, &mut sink);
171 if let Some(err) = sink.into_inner() {
172 Err(err)
173 } else {
174 for key in &mut keys {
175 key.despan(s);
176 }
177 Ok(keys)
178 }
179 }
180}
181
182impl Clone for Key {
183 #[inline(never)]
184 fn clone(&self) -> Self {
185 Self {
186 key: self.key.clone(),
187 repr: self.repr.clone(),
188 leaf_decor: self.leaf_decor.clone(),
189 dotted_decor: self.dotted_decor.clone(),
190 }
191 }
192}
193
194impl std::ops::Deref for Key {
195 type Target = str;
196
197 fn deref(&self) -> &Self::Target {
198 self.get()
199 }
200}
201
202impl std::borrow::Borrow<str> for Key {
203 #[inline]
204 fn borrow(&self) -> &str {
205 self.get()
206 }
207}
208
209impl std::hash::Hash for Key {
210 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
211 self.get().hash(state);
212 }
213}
214
215impl Ord for Key {
216 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
217 self.get().cmp(other.get())
218 }
219}
220
221impl PartialOrd for Key {
222 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
223 Some(self.cmp(other))
224 }
225}
226
227impl Eq for Key {}
228
229impl PartialEq for Key {
230 #[inline]
231 fn eq(&self, other: &Self) -> bool {
232 PartialEq::eq(self.get(), other.get())
233 }
234}
235
236impl PartialEq<str> for Key {
237 #[inline]
238 fn eq(&self, other: &str) -> bool {
239 PartialEq::eq(self.get(), other)
240 }
241}
242
243impl PartialEq<&str> for Key {
244 #[inline]
245 fn eq(&self, other: &&str) -> bool {
246 PartialEq::eq(self.get(), *other)
247 }
248}
249
250impl PartialEq<String> for Key {
251 #[inline]
252 fn eq(&self, other: &String) -> bool {
253 PartialEq::eq(self.get(), other.as_str())
254 }
255}
256
257#[cfg(feature = "display")]
258impl std::fmt::Display for Key {
259 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260 crate::encode::encode_key(self, f, None)
261 }
262}
263
264#[cfg(feature = "parse")]
265impl FromStr for Key {
266 type Err = crate::TomlError;
267
268 fn from_str(s: &str) -> Result<Self, Self::Err> {
272 Self::try_parse_simple(s)
273 }
274}
275
276impl<'b> From<&'b str> for Key {
277 fn from(s: &'b str) -> Self {
278 Self::new(s)
279 }
280}
281
282impl<'b> From<&'b String> for Key {
283 fn from(s: &'b String) -> Self {
284 Self::new(s)
285 }
286}
287
288impl From<String> for Key {
289 fn from(s: String) -> Self {
290 Self::new(s)
291 }
292}
293
294#[doc(hidden)]
295impl From<Key> for String {
296 fn from(key: Key) -> Self {
297 key.key
298 }
299}
300
301#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
303pub struct KeyMut<'k> {
304 key: &'k mut Key,
305}
306
307impl KeyMut<'_> {
308 pub fn get(&self) -> &str {
310 self.key.get()
311 }
312
313 pub fn as_repr(&self) -> Option<&Repr> {
315 self.key.as_repr()
316 }
317
318 #[cfg(feature = "display")]
320 pub fn default_repr(&self) -> Repr {
321 self.key.default_repr()
322 }
323
324 #[cfg(feature = "display")]
326 pub fn display_repr(&self) -> Cow<'_, str> {
327 self.key.display_repr()
328 }
329
330 pub fn leaf_decor_mut(&mut self) -> &mut Decor {
332 self.key.leaf_decor_mut()
333 }
334
335 pub fn dotted_decor_mut(&mut self) -> &mut Decor {
337 self.key.dotted_decor_mut()
338 }
339
340 pub fn leaf_decor(&self) -> &Decor {
342 self.key.leaf_decor()
343 }
344
345 pub fn dotted_decor(&self) -> &Decor {
347 self.key.dotted_decor()
348 }
349
350 pub fn fmt(&mut self) {
352 self.key.fmt();
353 }
354}
355
356impl std::ops::Deref for KeyMut<'_> {
357 type Target = str;
358
359 fn deref(&self) -> &Self::Target {
360 self.get()
361 }
362}
363
364impl PartialEq<str> for KeyMut<'_> {
365 #[inline]
366 fn eq(&self, other: &str) -> bool {
367 PartialEq::eq(self.get(), other)
368 }
369}
370
371impl<'s> PartialEq<&'s str> for KeyMut<'s> {
372 #[inline]
373 fn eq(&self, other: &&str) -> bool {
374 PartialEq::eq(self.get(), *other)
375 }
376}
377
378impl PartialEq<String> for KeyMut<'_> {
379 #[inline]
380 fn eq(&self, other: &String) -> bool {
381 PartialEq::eq(self.get(), other.as_str())
382 }
383}
384
385#[cfg(feature = "display")]
386impl std::fmt::Display for KeyMut<'_> {
387 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388 std::fmt::Display::fmt(&self.key, f)
389 }
390}
391
392#[test]
393#[cfg(feature = "parse")]
394#[cfg(feature = "display")]
395fn string_roundtrip() {
396 Key::new("hello").to_string().parse::<Key>().unwrap();
397}