Skip to main content

log/kv/
key.rs

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