xisf_header/key.rs
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! The unified [`Key`] used to address keywords.
6
7/// Addresses a keyword either by name (strict: it must be unique) or by a
8/// specific occurrence when a name repeats.
9///
10/// You rarely name `Key` directly — every keyword accessor takes
11/// `impl Into<Key>`, so both forms work:
12///
13/// ```
14/// use xisf_header::Header;
15/// let mut h = Header::new();
16/// h.append("HISTORY", "first").unwrap();
17/// h.append("HISTORY", "second").unwrap();
18///
19/// // Bare name is ambiguous here → error; select an occurrence instead.
20/// assert!(h.get_str("HISTORY").is_err());
21/// assert_eq!(h.get_str(("HISTORY", 1)).unwrap(), Some("second"));
22/// ```
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum Key<'a> {
25 /// Match the sole keyword with this name (ambiguous if it repeats).
26 Name(&'a str),
27 /// Match the `usize`-th (0-based) occurrence of this name.
28 Nth(&'a str, usize),
29}
30
31impl<'a> Key<'a> {
32 /// The keyword name this key addresses.
33 ///
34 /// ```
35 /// use xisf_header::Key;
36 ///
37 /// let key: Key = ("HISTORY", 1).into();
38 /// assert_eq!(key.name(), "HISTORY");
39 /// ```
40 #[must_use]
41 pub fn name(&self) -> &'a str {
42 match *self {
43 Key::Name(n) | Key::Nth(n, _) => n,
44 }
45 }
46}
47
48impl<'a> From<&'a str> for Key<'a> {
49 fn from(name: &'a str) -> Self {
50 Key::Name(name)
51 }
52}
53
54impl<'a> From<&'a String> for Key<'a> {
55 fn from(name: &'a String) -> Self {
56 Key::Name(name)
57 }
58}
59
60impl<'a> From<(&'a str, usize)> for Key<'a> {
61 fn from((name, n): (&'a str, usize)) -> Self {
62 Key::Nth(name, n)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn conversions_and_name() {
72 let by_name: Key = "GAIN".into();
73 assert_eq!(by_name, Key::Name("GAIN"));
74 assert_eq!(by_name.name(), "GAIN");
75
76 let owned = String::from("GAIN");
77 let from_string: Key = (&owned).into();
78 assert_eq!(from_string, Key::Name("GAIN"));
79
80 let nth: Key = ("HISTORY", 2).into();
81 assert_eq!(nth, Key::Nth("HISTORY", 2));
82 assert_eq!(nth.name(), "HISTORY");
83 }
84}