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<'a, T> ToKey for &'a 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    pub fn from_str(key: &'k str) -> Self {
45        Key { key }
46    }
47
48    /// Get a borrowed string from this key.
49    ///
50    /// The lifetime of the returned string is bound to the borrow of `self` rather
51    /// than to `'k`.
52    pub fn as_str(&self) -> &str {
53        self.key
54    }
55
56    /// Try get a borrowed string for the lifetime `'k` from this key.
57    ///
58    /// If the key is a borrow of a longer lived string, this method will return `Some`.
59    /// If the key is internally buffered, this method will return `None`.
60    pub fn to_borrowed_str(&self) -> Option<&'k str> {
61        // NOTE: If the internals of `Key` support buffering this
62        // won't be unconditionally `Some` anymore. We want to keep
63        // this option open
64        Some(self.key)
65    }
66}
67
68impl<'k> fmt::Display for Key<'k> {
69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70        self.key.fmt(f)
71    }
72}
73
74impl<'k> AsRef<str> for Key<'k> {
75    fn as_ref(&self) -> &str {
76        self.as_str()
77    }
78}
79
80impl<'k> Borrow<str> for Key<'k> {
81    fn borrow(&self) -> &str {
82        self.as_str()
83    }
84}
85
86impl<'k> From<&'k str> for Key<'k> {
87    fn from(s: &'k str) -> Self {
88        Key::from_str(s)
89    }
90}
91
92#[cfg(feature = "std")]
93mod std_support {
94    use super::*;
95
96    use std::borrow::Cow;
97
98    impl ToKey for String {
99        fn to_key(&self) -> Key {
100            Key::from_str(self)
101        }
102    }
103
104    impl<'a> ToKey for Cow<'a, str> {
105        fn to_key(&self) -> Key {
106            Key::from_str(self)
107        }
108    }
109}
110
111#[cfg(feature = "kv_sval")]
112mod sval_support {
113    use super::*;
114
115    use sval::Value;
116    use sval_ref::ValueRef;
117
118    impl<'a> Value for Key<'a> {
119        fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(
120            &'sval self,
121            stream: &mut S,
122        ) -> sval::Result {
123            self.key.stream(stream)
124        }
125    }
126
127    impl<'a> ValueRef<'a> for Key<'a> {
128        fn stream_ref<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result {
129            self.key.stream(stream)
130        }
131    }
132}
133
134#[cfg(feature = "kv_serde")]
135mod serde_support {
136    use super::*;
137
138    use serde::{Serialize, Serializer};
139
140    impl<'a> Serialize for Key<'a> {
141        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
142        where
143            S: Serializer,
144        {
145            self.key.serialize(serializer)
146        }
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::*;
153
154    #[test]
155    fn key_from_string() {
156        assert_eq!("a key", Key::from_str("a key").as_str());
157    }
158
159    #[test]
160    fn key_to_borrowed() {
161        assert_eq!("a key", Key::from_str("a key").to_borrowed_str().unwrap());
162    }
163}