tonic/metadata/
key.rs
1use bytes::Bytes;
2use http::header::HeaderName;
3use std::borrow::Borrow;
4use std::error::Error;
5use std::fmt;
6use std::marker::PhantomData;
7use std::str::FromStr;
8
9use super::encoding::{Ascii, Binary, ValueEncoding};
10
11#[derive(Clone, Eq, PartialEq, Hash)]
18#[repr(transparent)]
19pub struct MetadataKey<VE: ValueEncoding> {
20 pub(crate) inner: http::header::HeaderName,
23 phantom: PhantomData<VE>,
24}
25
26#[derive(Debug, Default)]
28pub struct InvalidMetadataKey {
29 _priv: (),
30}
31
32pub type AsciiMetadataKey = MetadataKey<Ascii>;
34pub type BinaryMetadataKey = MetadataKey<Binary>;
36
37impl<VE: ValueEncoding> MetadataKey<VE> {
38 pub fn from_bytes(src: &[u8]) -> Result<Self, InvalidMetadataKey> {
42 match HeaderName::from_bytes(src) {
43 Ok(name) => {
44 if !VE::is_valid_key(name.as_str()) {
45 return Err(InvalidMetadataKey::new());
46 }
47
48 Ok(MetadataKey {
49 inner: name,
50 phantom: PhantomData,
51 })
52 }
53 Err(_) => Err(InvalidMetadataKey::new()),
54 }
55 }
56
57 pub fn from_static(src: &'static str) -> Self {
103 let name = HeaderName::from_static(src);
104 if !VE::is_valid_key(name.as_str()) {
105 panic!("invalid metadata key")
106 }
107
108 MetadataKey {
109 inner: name,
110 phantom: PhantomData,
111 }
112 }
113
114 #[inline]
118 pub fn as_str(&self) -> &str {
119 self.inner.as_str()
120 }
121
122 #[inline]
126 pub(crate) fn unchecked_from_header_name_ref(header_name: &HeaderName) -> &Self {
127 unsafe { &*(header_name as *const HeaderName as *const Self) }
128 }
129
130 #[inline]
134 pub(crate) fn unchecked_from_header_name(name: HeaderName) -> Self {
135 MetadataKey {
136 inner: name,
137 phantom: PhantomData,
138 }
139 }
140}
141
142impl<VE: ValueEncoding> FromStr for MetadataKey<VE> {
143 type Err = InvalidMetadataKey;
144
145 fn from_str(s: &str) -> Result<Self, InvalidMetadataKey> {
146 MetadataKey::from_bytes(s.as_bytes()).map_err(|_| InvalidMetadataKey::new())
147 }
148}
149
150impl<VE: ValueEncoding> AsRef<str> for MetadataKey<VE> {
151 fn as_ref(&self) -> &str {
152 self.as_str()
153 }
154}
155
156impl<VE: ValueEncoding> AsRef<[u8]> for MetadataKey<VE> {
157 fn as_ref(&self) -> &[u8] {
158 self.as_str().as_bytes()
159 }
160}
161
162impl<VE: ValueEncoding> Borrow<str> for MetadataKey<VE> {
163 fn borrow(&self) -> &str {
164 self.as_str()
165 }
166}
167
168impl<VE: ValueEncoding> fmt::Debug for MetadataKey<VE> {
169 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
170 fmt::Debug::fmt(self.as_str(), fmt)
171 }
172}
173
174impl<VE: ValueEncoding> fmt::Display for MetadataKey<VE> {
175 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
176 fmt::Display::fmt(self.as_str(), fmt)
177 }
178}
179
180impl InvalidMetadataKey {
181 #[doc(hidden)]
182 pub fn new() -> InvalidMetadataKey {
183 Self::default()
184 }
185}
186
187impl<'a, VE: ValueEncoding> From<&'a MetadataKey<VE>> for MetadataKey<VE> {
188 fn from(src: &'a MetadataKey<VE>) -> MetadataKey<VE> {
189 src.clone()
190 }
191}
192
193impl<VE: ValueEncoding> From<MetadataKey<VE>> for Bytes {
194 #[inline]
195 fn from(name: MetadataKey<VE>) -> Bytes {
196 Bytes::copy_from_slice(name.inner.as_ref())
197 }
198}
199
200impl<'a, VE: ValueEncoding> PartialEq<&'a MetadataKey<VE>> for MetadataKey<VE> {
201 #[inline]
202 fn eq(&self, other: &&'a MetadataKey<VE>) -> bool {
203 *self == **other
204 }
205}
206
207impl<'a, VE: ValueEncoding> PartialEq<MetadataKey<VE>> for &'a MetadataKey<VE> {
208 #[inline]
209 fn eq(&self, other: &MetadataKey<VE>) -> bool {
210 *other == *self
211 }
212}
213
214impl<VE: ValueEncoding> PartialEq<str> for MetadataKey<VE> {
215 #[inline]
229 fn eq(&self, other: &str) -> bool {
230 self.inner.eq(other)
231 }
232}
233
234impl<VE: ValueEncoding> PartialEq<MetadataKey<VE>> for str {
235 #[inline]
249 fn eq(&self, other: &MetadataKey<VE>) -> bool {
250 other.inner == *self
251 }
252}
253
254impl<'a, VE: ValueEncoding> PartialEq<&'a str> for MetadataKey<VE> {
255 #[inline]
258 fn eq(&self, other: &&'a str) -> bool {
259 *self == **other
260 }
261}
262
263impl<'a, VE: ValueEncoding> PartialEq<MetadataKey<VE>> for &'a str {
264 #[inline]
267 fn eq(&self, other: &MetadataKey<VE>) -> bool {
268 *other == *self
269 }
270}
271
272impl fmt::Display for InvalidMetadataKey {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 f.write_str("invalid gRPC metadata key name")
275 }
276}
277
278impl Error for InvalidMetadataKey {}
279
280#[cfg(test)]
281mod tests {
282 use super::{AsciiMetadataKey, BinaryMetadataKey};
283
284 #[test]
285 fn test_from_bytes_binary() {
286 assert!(BinaryMetadataKey::from_bytes(b"").is_err());
287 assert!(BinaryMetadataKey::from_bytes(b"\xFF").is_err());
288 assert!(BinaryMetadataKey::from_bytes(b"abc").is_err());
289 assert_eq!(
290 BinaryMetadataKey::from_bytes(b"abc-bin").unwrap().as_str(),
291 "abc-bin"
292 );
293 }
294
295 #[test]
296 fn test_from_bytes_ascii() {
297 assert!(AsciiMetadataKey::from_bytes(b"").is_err());
298 assert!(AsciiMetadataKey::from_bytes(b"\xFF").is_err());
299 assert_eq!(
300 AsciiMetadataKey::from_bytes(b"abc").unwrap().as_str(),
301 "abc"
302 );
303 assert!(AsciiMetadataKey::from_bytes(b"abc-bin").is_err());
304 }
305}