1 //! Structured keys. 2 3 use std::borrow::Borrow; 4 use std::fmt; 5 6 /// A type that can be converted into a [`Key`](struct.Key.html). 7 pub trait ToKey { 8 /// Perform the conversion. to_key(&self) -> Key9 fn to_key(&self) -> Key; 10 } 11 12 impl<'a, T> ToKey for &'a T 13 where 14 T: ToKey + ?Sized, 15 { to_key(&self) -> Key16 fn to_key(&self) -> Key { 17 (**self).to_key() 18 } 19 } 20 21 impl<'k> ToKey for Key<'k> { to_key(&self) -> Key22 fn to_key(&self) -> Key { 23 Key { key: self.key } 24 } 25 } 26 27 impl ToKey for str { to_key(&self) -> Key28 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)] 37 pub struct Key<'k> { 38 // NOTE: This may become `Cow<'k, str>` 39 key: &'k str, 40 } 41 42 impl<'k> Key<'k> { 43 /// Get a key from a borrowed string. from_str(key: &'k str) -> Self44 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`. as_str(&self) -> &str52 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`. to_borrowed_str(&self) -> Option<&'k str>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 68 impl<'k> fmt::Display for Key<'k> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 70 self.key.fmt(f) 71 } 72 } 73 74 impl<'k> AsRef<str> for Key<'k> { as_ref(&self) -> &str75 fn as_ref(&self) -> &str { 76 self.as_str() 77 } 78 } 79 80 impl<'k> Borrow<str> for Key<'k> { borrow(&self) -> &str81 fn borrow(&self) -> &str { 82 self.as_str() 83 } 84 } 85 86 impl<'k> From<&'k str> for Key<'k> { from(s: &'k str) -> Self87 fn from(s: &'k str) -> Self { 88 Key::from_str(s) 89 } 90 } 91 92 #[cfg(feature = "std")] 93 mod std_support { 94 use super::*; 95 96 use std::borrow::Cow; 97 98 impl ToKey for String { to_key(&self) -> Key99 fn to_key(&self) -> Key { 100 Key::from_str(self) 101 } 102 } 103 104 impl<'a> ToKey for Cow<'a, str> { to_key(&self) -> Key105 fn to_key(&self) -> Key { 106 Key::from_str(self) 107 } 108 } 109 } 110 111 #[cfg(feature = "kv_sval")] 112 mod sval_support { 113 use super::*; 114 115 use sval::Value; 116 use sval_ref::ValueRef; 117 118 impl<'a> Value for Key<'a> { stream<'sval, S: sval::Stream<'sval> + ?Sized>( &'sval self, stream: &mut S, ) -> sval::Result119 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> { stream_ref<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result128 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")] 135 mod serde_support { 136 use super::*; 137 138 use serde::{Serialize, Serializer}; 139 140 impl<'a> Serialize for Key<'a> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,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)] 151 mod tests { 152 use super::*; 153 154 #[test] key_from_string()155 fn key_from_string() { 156 assert_eq!("a key", Key::from_str("a key").as_str()); 157 } 158 159 #[test] key_to_borrowed()160 fn key_to_borrowed() { 161 assert_eq!("a key", Key::from_str("a key").to_borrowed_str().unwrap()); 162 } 163 } 164