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. |
9 | fn to_key(&self) -> Key; |
10 | } |
11 | |
12 | impl<'a, T> ToKey for &'a T |
13 | where |
14 | T: ToKey + ?Sized, |
15 | { |
16 | fn to_key(&self) -> Key { |
17 | (**self).to_key() |
18 | } |
19 | } |
20 | |
21 | impl<'k> ToKey for Key<'k> { |
22 | fn to_key(&self) -> Key { |
23 | Key { key: self.key } |
24 | } |
25 | } |
26 | |
27 | impl 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)] |
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. |
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 | |
68 | impl<'k> fmt::Display for Key<'k> { |
69 | 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> { |
75 | fn as_ref(&self) -> &str { |
76 | self.as_str() |
77 | } |
78 | } |
79 | |
80 | impl<'k> Borrow<str> for Key<'k> { |
81 | fn borrow(&self) -> &str { |
82 | self.as_str() |
83 | } |
84 | } |
85 | |
86 | impl<'k> From<&'k str> for Key<'k> { |
87 | fn from(s: &'k str) -> Self { |
88 | Key::from_str(key: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 { |
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" )] |
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> { |
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" )] |
135 | mod 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)] |
151 | mod 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 | } |
164 | |