Skip to main content

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}