log/kv/
key.rs

1//! Structured keys.
2
3use std::borrow::Borrow;
4use std::fmt;
5
6/// A type that can be converted into a [`Key`](struct.Key.html).
7pub trait ToKey {
8    /// Perform the conversion.
9    fn to_key(&self) -> Key<'_>;
10}
11
12impl<T> ToKey for &T
13where
14    T: ToKey + ?Sized,
15{
16    fn to_key(&self) -> Key<'_> {
17        (**self).to_key()
18    }
19}
20
21impl<'k> ToKey for Key<'k> {
22    fn to_key(&self) -> Key<'_> {
23        Key { key: self.key }
24    }
25}
26
27impl ToKey for str {
28    fn to_key(&self) -> Key<'_> {
29        Key::from_str(self)
30    }
31}
32
33/// A key in a key-value.
34// These impls must only be based on the as_str() representation of the key
35// If a new field (such as an optional index) is added to the key they must not affect comparison
36#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct Key<'k> {
38    // NOTE: This may become `Cow<'k, str>`
39    key: &'k str,
40}
41
42impl<'k> Key<'k> {
43    /// Get a key from a borrowed string.
44    #[allow(clippy::should_implement_trait)] // Part of the public API now.
45    pub fn from_str(key: &'k str) -> Self {
46        Key { key }
47    }
48
49    /// Get a borrowed string from this key.
50    ///
51    /// The lifetime of the returned string is bound to the borrow of `self` rather
52    /// than to `'k`.
53    pub fn as_str(&self) -> &str {
54        self.key
55    }
56
57    /// Try get a borrowed string for the lifetime `'k` from this key.
58    ///
59    /// If the key is a borrow of a longer lived string, this method will return `Some`.
60    /// If the key is internally buffered, this method will return `None`.
61    pub fn to_borrowed_str(&self) -> Option<&'k str> {
62        // NOTE: If the internals of `Key` support buffering this
63        // won't be unconditionally `Some` anymore. We want to keep
64        // this option open
65        Some(self.key)
66    }
67}
68
69impl<'k> fmt::Display for Key<'k> {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        self.key.fmt(f)
72    }
73}
74
75impl<'k> AsRef<str> for Key<'k> {
76    fn as_ref(&self) -> &str {
77        self.as_str()
78    }
79}
80
81impl<'k> Borrow<str> for Key<'k> {
82    fn borrow(&self) -> &str {
83        self.as_str()
84    }
85}
86
87impl<'k> From<&'k str> for Key<'k> {
88    fn from(s: &'k str) -> Self {
89        Key::from_str(s)
90    }
91}
92
93#[cfg(feature = "std")]
94mod std_support {
95    use super::*;
96
97    use std::borrow::Cow;
98
99    impl ToKey for String {
100        fn to_key(&self) -> Key<'_> {
101            Key::from_str(self)
102        }
103    }
104
105    impl<'a> ToKey for Cow<'a, str> {
106        fn to_key(&self) -> Key<'_> {
107            Key::from_str(self)
108        }
109    }
110}
111
112#[cfg(feature = "kv_sval")]
113mod sval_support {
114    use super::*;
115
116    use sval::Value;
117    use sval_ref::ValueRef;
118
119    impl<'a> Value for Key<'a> {
120        fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(
121            &'sval self,
122            stream: &mut S,
123        ) -> sval::Result {
124            self.key.stream(stream)
125        }
126    }
127
128    impl<'a> ValueRef<'a> for Key<'a> {
129        fn stream_ref<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result {
130            self.key.stream(stream)
131        }
132    }
133}
134
135#[cfg(feature = "kv_serde")]
136mod serde_support {
137    use super::*;
138
139    use serde_core::{Serialize, Serializer};
140
141    impl<'a> Serialize for Key<'a> {
142        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
143        where
144            S: Serializer,
145        {
146            self.key.serialize(serializer)
147        }
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154
155    #[test]
156    fn key_from_string() {
157        assert_eq!("a key", Key::from_str("a key").as_str());
158    }
159
160    #[test]
161    fn key_to_borrowed() {
162        assert_eq!("a key", Key::from_str("a key").to_borrowed_str().unwrap());
163    }
164}