1 #![allow(clippy::upper_case_acronyms)]
2
3 use super::encoding::{
4 Ascii, Binary, InvalidMetadataValue, InvalidMetadataValueBytes, ValueEncoding,
5 };
6 use super::key::MetadataKey;
7
8 use bytes::Bytes;
9 use http::header::HeaderValue;
10 use std::error::Error;
11 use std::hash::{Hash, Hasher};
12 use std::marker::PhantomData;
13 use std::str::FromStr;
14 use std::{cmp, fmt};
15
16 /// Represents a custom metadata field value.
17 ///
18 /// `MetadataValue` is used as the [`MetadataMap`] value.
19 ///
20 /// [`HeaderMap`]: struct.HeaderMap.html
21 /// [`MetadataMap`]: struct.MetadataMap.html
22 #[derive(Clone)]
23 #[repr(transparent)]
24 pub struct MetadataValue<VE: ValueEncoding> {
25 // Note: There are unsafe transmutes that assume that the memory layout
26 // of MetadataValue is identical to HeaderValue
27 pub(crate) inner: HeaderValue,
28 phantom: PhantomData<VE>,
29 }
30
31 /// A possible error when converting a `MetadataValue` to a string representation.
32 ///
33 /// Metadata field values may contain opaque bytes, in which case it is not
34 /// possible to represent the value as a string.
35 #[derive(Debug)]
36 pub struct ToStrError {
37 _priv: (),
38 }
39
40 /// An ascii metadata value.
41 pub type AsciiMetadataValue = MetadataValue<Ascii>;
42 /// A binary metadata value.
43 pub type BinaryMetadataValue = MetadataValue<Binary>;
44
45 impl<VE: ValueEncoding> MetadataValue<VE> {
46 /// Convert a static string to a `MetadataValue`.
47 ///
48 /// This function will not perform any copying, however the string is
49 /// checked to ensure that no invalid characters are present.
50 ///
51 /// For Ascii values, only visible ASCII characters (32-127) are permitted.
52 /// For Binary values, the string must be valid base64.
53 ///
54 /// # Panics
55 ///
56 /// This function panics if the argument contains invalid metadata value
57 /// characters.
58 ///
59 /// # Examples
60 ///
61 /// ```
62 /// # use tonic::metadata::*;
63 /// let val = AsciiMetadataValue::from_static("hello");
64 /// assert_eq!(val, "hello");
65 /// ```
66 ///
67 /// ```
68 /// # use tonic::metadata::*;
69 /// let val = BinaryMetadataValue::from_static("SGVsbG8hIQ==");
70 /// assert_eq!(val, "Hello!!");
71 /// ```
72 #[inline]
from_static(src: &'static str) -> Self73 pub fn from_static(src: &'static str) -> Self {
74 MetadataValue {
75 inner: VE::from_static(src),
76 phantom: PhantomData,
77 }
78 }
79
80 /// Convert a `Bytes` directly into a `MetadataValue` without validating.
81 /// For `MetadataValue<Binary>` the provided parameter must be base64
82 /// encoded without padding bytes at the end.
83 ///
84 /// # Safety
85 ///
86 /// This function does NOT validate that illegal bytes are not contained
87 /// within the buffer.
88 #[inline]
from_shared_unchecked(src: Bytes) -> Self89 pub unsafe fn from_shared_unchecked(src: Bytes) -> Self {
90 MetadataValue {
91 inner: HeaderValue::from_maybe_shared_unchecked(src),
92 phantom: PhantomData,
93 }
94 }
95
96 /// Returns true if the `MetadataValue` has a length of zero bytes.
97 ///
98 /// # Examples
99 ///
100 /// ```
101 /// # use tonic::metadata::*;
102 /// let val = AsciiMetadataValue::from_static("");
103 /// assert!(val.is_empty());
104 ///
105 /// let val = AsciiMetadataValue::from_static("hello");
106 /// assert!(!val.is_empty());
107 /// ```
108 #[inline]
is_empty(&self) -> bool109 pub fn is_empty(&self) -> bool {
110 VE::is_empty(self.inner.as_bytes())
111 }
112
113 /// Converts a `MetadataValue` to a Bytes buffer. This method cannot
114 /// fail for Ascii values. For Ascii values, `as_bytes` is more convenient
115 /// to use.
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// # use tonic::metadata::*;
121 /// let val = AsciiMetadataValue::from_static("hello");
122 /// assert_eq!(val.to_bytes().unwrap().as_ref(), b"hello");
123 /// ```
124 ///
125 /// ```
126 /// # use tonic::metadata::*;
127 /// let val = BinaryMetadataValue::from_bytes(b"hello");
128 /// assert_eq!(val.to_bytes().unwrap().as_ref(), b"hello");
129 /// ```
130 #[inline]
to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes>131 pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
132 VE::decode(self.inner.as_bytes())
133 }
134
135 /// Mark that the metadata value represents sensitive information.
136 ///
137 /// # Examples
138 ///
139 /// ```
140 /// # use tonic::metadata::*;
141 /// let mut val = AsciiMetadataValue::from_static("my secret");
142 ///
143 /// val.set_sensitive(true);
144 /// assert!(val.is_sensitive());
145 ///
146 /// val.set_sensitive(false);
147 /// assert!(!val.is_sensitive());
148 /// ```
149 #[inline]
set_sensitive(&mut self, val: bool)150 pub fn set_sensitive(&mut self, val: bool) {
151 self.inner.set_sensitive(val);
152 }
153
154 /// Returns `true` if the value represents sensitive data.
155 ///
156 /// Sensitive data could represent passwords or other data that should not
157 /// be stored on disk or in memory. This setting can be used by components
158 /// like caches to avoid storing the value. HPACK encoders must set the
159 /// metadata field to never index when `is_sensitive` returns true.
160 ///
161 /// Note that sensitivity is not factored into equality or ordering.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// # use tonic::metadata::*;
167 /// let mut val = AsciiMetadataValue::from_static("my secret");
168 ///
169 /// val.set_sensitive(true);
170 /// assert!(val.is_sensitive());
171 ///
172 /// val.set_sensitive(false);
173 /// assert!(!val.is_sensitive());
174 /// ```
175 #[inline]
is_sensitive(&self) -> bool176 pub fn is_sensitive(&self) -> bool {
177 self.inner.is_sensitive()
178 }
179
180 /// Converts a `MetadataValue` to a byte slice. For Binary values, the
181 /// return value is base64 encoded.
182 ///
183 /// # Examples
184 ///
185 /// ```
186 /// # use tonic::metadata::*;
187 /// let val = AsciiMetadataValue::from_static("hello");
188 /// assert_eq!(val.as_encoded_bytes(), b"hello");
189 /// ```
190 ///
191 /// ```
192 /// # use tonic::metadata::*;
193 /// let val = BinaryMetadataValue::from_bytes(b"Hello!");
194 /// assert_eq!(val.as_encoded_bytes(), b"SGVsbG8h");
195 /// ```
196 #[inline]
as_encoded_bytes(&self) -> &[u8]197 pub fn as_encoded_bytes(&self) -> &[u8] {
198 self.inner.as_bytes()
199 }
200
201 /// Converts a HeaderValue to a MetadataValue. This method assumes that the
202 /// caller has made sure that the value is of the correct Ascii or Binary
203 /// value encoding.
204 #[inline]
unchecked_from_header_value(value: HeaderValue) -> Self205 pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
206 MetadataValue {
207 inner: value,
208 phantom: PhantomData,
209 }
210 }
211
212 /// Converts a HeaderValue reference to a MetadataValue. This method assumes
213 /// that the caller has made sure that the value is of the correct Ascii or
214 /// Binary value encoding.
215 #[inline]
unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self216 pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self {
217 unsafe { &*(header_value as *const HeaderValue as *const Self) }
218 }
219
220 /// Converts a HeaderValue reference to a MetadataValue. This method assumes
221 /// that the caller has made sure that the value is of the correct Ascii or
222 /// Binary value encoding.
223 #[inline]
unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self224 pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self {
225 unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) }
226 }
227 }
228
229 /// Attempt to convert a byte slice to a `MetadataValue`.
230 ///
231 /// For Ascii metadata values, If the argument contains invalid metadata
232 /// value bytes, an error is returned. Only byte values between 32 and 255
233 /// (inclusive) are permitted, excluding byte 127 (DEL).
234 ///
235 /// For Binary metadata values this method cannot fail. See also the Binary
236 /// only version of this method `from_bytes`.
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// # use tonic::metadata::*;
242 /// let val = AsciiMetadataValue::try_from(b"hello\xfa").unwrap();
243 /// assert_eq!(val, &b"hello\xfa"[..]);
244 /// ```
245 ///
246 /// An invalid value
247 ///
248 /// ```
249 /// # use tonic::metadata::*;
250 /// let val = AsciiMetadataValue::try_from(b"\n");
251 /// assert!(val.is_err());
252 /// ```
253 impl<'a, VE: ValueEncoding> TryFrom<&'a [u8]> for MetadataValue<VE> {
254 type Error = InvalidMetadataValueBytes;
255
256 #[inline]
try_from(src: &[u8]) -> Result<Self, Self::Error>257 fn try_from(src: &[u8]) -> Result<Self, Self::Error> {
258 VE::from_bytes(src).map(|value| MetadataValue {
259 inner: value,
260 phantom: PhantomData,
261 })
262 }
263 }
264
265 /// Attempt to convert a byte slice to a `MetadataValue`.
266 ///
267 /// For Ascii metadata values, If the argument contains invalid metadata
268 /// value bytes, an error is returned. Only byte values between 32 and 255
269 /// (inclusive) are permitted, excluding byte 127 (DEL).
270 ///
271 /// For Binary metadata values this method cannot fail. See also the Binary
272 /// only version of this method `from_bytes`.
273 ///
274 /// # Examples
275 ///
276 /// ```
277 /// # use tonic::metadata::*;
278 /// let val = AsciiMetadataValue::try_from(b"hello\xfa").unwrap();
279 /// assert_eq!(val, &b"hello\xfa"[..]);
280 /// ```
281 ///
282 /// An invalid value
283 ///
284 /// ```
285 /// # use tonic::metadata::*;
286 /// let val = AsciiMetadataValue::try_from(b"\n");
287 /// assert!(val.is_err());
288 /// ```
289 impl<'a, VE: ValueEncoding, const N: usize> TryFrom<&'a [u8; N]> for MetadataValue<VE> {
290 type Error = InvalidMetadataValueBytes;
291
292 #[inline]
try_from(src: &[u8; N]) -> Result<Self, Self::Error>293 fn try_from(src: &[u8; N]) -> Result<Self, Self::Error> {
294 Self::try_from(src.as_ref())
295 }
296 }
297
298 /// Attempt to convert a `Bytes` buffer to a `MetadataValue`.
299 ///
300 /// For `MetadataValue<Ascii>`, if the argument contains invalid metadata
301 /// value bytes, an error is returned. Only byte values between 32 and 255
302 /// (inclusive) are permitted, excluding byte 127 (DEL).
303 ///
304 /// For `MetadataValue<Binary>`, if the argument is not valid base64, an
305 /// error is returned. In use cases where the input is not base64 encoded,
306 /// use `from_bytes`; if the value has to be encoded it's not possible to
307 /// share the memory anyways.
308 impl<VE: ValueEncoding> TryFrom<Bytes> for MetadataValue<VE> {
309 type Error = InvalidMetadataValueBytes;
310
311 #[inline]
try_from(src: Bytes) -> Result<Self, Self::Error>312 fn try_from(src: Bytes) -> Result<Self, Self::Error> {
313 VE::from_shared(src).map(|value| MetadataValue {
314 inner: value,
315 phantom: PhantomData,
316 })
317 }
318 }
319
320 /// Attempt to convert a Vec of bytes to a `MetadataValue`.
321 ///
322 /// For `MetadataValue<Ascii>`, if the argument contains invalid metadata
323 /// value bytes, an error is returned. Only byte values between 32 and 255
324 /// (inclusive) are permitted, excluding byte 127 (DEL).
325 ///
326 /// For `MetadataValue<Binary>`, if the argument is not valid base64, an
327 /// error is returned. In use cases where the input is not base64 encoded,
328 /// use `from_bytes`; if the value has to be encoded it's not possible to
329 /// share the memory anyways.
330 impl<VE: ValueEncoding> TryFrom<Vec<u8>> for MetadataValue<VE> {
331 type Error = InvalidMetadataValueBytes;
332
333 #[inline]
try_from(src: Vec<u8>) -> Result<Self, Self::Error>334 fn try_from(src: Vec<u8>) -> Result<Self, Self::Error> {
335 Self::try_from(src.as_slice())
336 }
337 }
338
339 /// Attempt to convert a string to a `MetadataValue<Ascii>`.
340 ///
341 /// If the argument contains invalid metadata value characters, an error is
342 /// returned. Only visible ASCII characters (32-127) are permitted. Use
343 /// `from_bytes` to create a `MetadataValue` that includes opaque octets
344 /// (128-255).
345 impl<'a> TryFrom<&'a str> for MetadataValue<Ascii> {
346 type Error = InvalidMetadataValue;
347
348 #[inline]
try_from(s: &'a str) -> Result<Self, Self::Error>349 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
350 s.parse()
351 }
352 }
353
354 /// Attempt to convert a string to a `MetadataValue<Ascii>`.
355 ///
356 /// If the argument contains invalid metadata value characters, an error is
357 /// returned. Only visible ASCII characters (32-127) are permitted. Use
358 /// `from_bytes` to create a `MetadataValue` that includes opaque octets
359 /// (128-255).
360 impl<'a> TryFrom<&'a String> for MetadataValue<Ascii> {
361 type Error = InvalidMetadataValue;
362
363 #[inline]
try_from(s: &'a String) -> Result<Self, Self::Error>364 fn try_from(s: &'a String) -> Result<Self, Self::Error> {
365 s.parse()
366 }
367 }
368
369 /// Attempt to convert a string to a `MetadataValue<Ascii>`.
370 ///
371 /// If the argument contains invalid metadata value characters, an error is
372 /// returned. Only visible ASCII characters (32-127) are permitted. Use
373 /// `from_bytes` to create a `MetadataValue` that includes opaque octets
374 /// (128-255).
375 impl TryFrom<String> for MetadataValue<Ascii> {
376 type Error = InvalidMetadataValue;
377
378 #[inline]
try_from(s: String) -> Result<Self, Self::Error>379 fn try_from(s: String) -> Result<Self, Self::Error> {
380 s.parse()
381 }
382 }
383
384 // is_empty is defined in the generic impl block above
385 #[allow(clippy::len_without_is_empty)]
386 impl MetadataValue<Ascii> {
387 /// Converts a MetadataKey into a `MetadataValue<Ascii>`.
388 ///
389 /// Since every valid MetadataKey is a valid MetadataValue this is done
390 /// infallibly.
391 ///
392 /// # Examples
393 ///
394 /// ```
395 /// # use tonic::metadata::*;
396 /// let val = AsciiMetadataValue::from_key::<Ascii>("accept".parse().unwrap());
397 /// assert_eq!(val, AsciiMetadataValue::try_from(b"accept").unwrap());
398 /// ```
399 #[inline]
from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self400 pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
401 key.into()
402 }
403
404 /// Returns the length of `self`, in bytes.
405 ///
406 /// This method is not available for `MetadataValue<Binary>` because that
407 /// cannot be implemented in constant time, which most people would probably
408 /// expect. To get the length of `MetadataValue<Binary>`, convert it to a
409 /// Bytes value and measure its length.
410 ///
411 /// # Examples
412 ///
413 /// ```
414 /// # use tonic::metadata::*;
415 /// let val = AsciiMetadataValue::from_static("hello");
416 /// assert_eq!(val.len(), 5);
417 /// ```
418 #[inline]
len(&self) -> usize419 pub fn len(&self) -> usize {
420 self.inner.len()
421 }
422
423 /// Yields a `&str` slice if the `MetadataValue` only contains visible ASCII
424 /// chars.
425 ///
426 /// This function will perform a scan of the metadata value, checking all the
427 /// characters.
428 ///
429 /// # Examples
430 ///
431 /// ```
432 /// # use tonic::metadata::*;
433 /// let val = AsciiMetadataValue::from_static("hello");
434 /// assert_eq!(val.to_str().unwrap(), "hello");
435 /// ```
to_str(&self) -> Result<&str, ToStrError>436 pub fn to_str(&self) -> Result<&str, ToStrError> {
437 self.inner.to_str().map_err(|_| ToStrError::new())
438 }
439
440 /// Converts a `MetadataValue` to a byte slice. For Binary values, use
441 /// `to_bytes`.
442 ///
443 /// # Examples
444 ///
445 /// ```
446 /// # use tonic::metadata::*;
447 /// let val = AsciiMetadataValue::from_static("hello");
448 /// assert_eq!(val.as_bytes(), b"hello");
449 /// ```
450 #[inline]
as_bytes(&self) -> &[u8]451 pub fn as_bytes(&self) -> &[u8] {
452 self.inner.as_bytes()
453 }
454 }
455
456 impl MetadataValue<Binary> {
457 /// Convert a byte slice to a `MetadataValue<Binary>`.
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// # use tonic::metadata::*;
463 /// let val = BinaryMetadataValue::from_bytes(b"hello\xfa");
464 /// assert_eq!(val, &b"hello\xfa"[..]);
465 /// ```
466 #[inline]
from_bytes(src: &[u8]) -> Self467 pub fn from_bytes(src: &[u8]) -> Self {
468 // Only the Ascii version of try_from can fail.
469 Self::try_from(src).unwrap()
470 }
471 }
472
473 impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
474 #[inline]
as_ref(&self) -> &[u8]475 fn as_ref(&self) -> &[u8] {
476 self.inner.as_ref()
477 }
478 }
479
480 impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result481 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
482 VE::fmt(&self.inner, f)
483 }
484 }
485
486 impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
487 #[inline]
from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii>488 fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
489 MetadataValue {
490 inner: h.inner.into(),
491 phantom: PhantomData,
492 }
493 }
494 }
495
496 macro_rules! from_integers {
497 ($($name:ident: $t:ident => $max_len:expr),*) => {$(
498 impl From<$t> for MetadataValue<Ascii> {
499 fn from(num: $t) -> MetadataValue<Ascii> {
500 MetadataValue {
501 inner: HeaderValue::from(num),
502 phantom: PhantomData,
503 }
504 }
505 }
506
507 #[test]
508 fn $name() {
509 let n: $t = 55;
510 let val = AsciiMetadataValue::from(n);
511 assert_eq!(val, &n.to_string());
512
513 let n = ::std::$t::MAX;
514 let val = AsciiMetadataValue::from(n);
515 assert_eq!(val, &n.to_string());
516 }
517 )*};
518 }
519
520 from_integers! {
521 // integer type => maximum decimal length
522
523 // u8 purposely left off... AsciiMetadataValue::from(b'3') could be confusing
524 from_u16: u16 => 5,
525 from_i16: i16 => 6,
526 from_u32: u32 => 10,
527 from_i32: i32 => 11,
528 from_u64: u64 => 20,
529 from_i64: i64 => 20
530 }
531
532 #[cfg(target_pointer_width = "16")]
533 from_integers! {
534 from_usize: usize => 5,
535 from_isize: isize => 6
536 }
537
538 #[cfg(target_pointer_width = "32")]
539 from_integers! {
540 from_usize: usize => 10,
541 from_isize: isize => 11
542 }
543
544 #[cfg(target_pointer_width = "64")]
545 from_integers! {
546 from_usize: usize => 20,
547 from_isize: isize => 20
548 }
549
550 #[cfg(test)]
551 mod from_metadata_value_tests {
552 use super::*;
553 use crate::metadata::map::MetadataMap;
554
555 #[test]
it_can_insert_metadata_key_as_metadata_value()556 fn it_can_insert_metadata_key_as_metadata_value() {
557 let mut map = MetadataMap::new();
558 map.insert(
559 "accept",
560 MetadataKey::<Ascii>::from_bytes(b"hello-world")
561 .unwrap()
562 .into(),
563 );
564
565 assert_eq!(
566 map.get("accept").unwrap(),
567 AsciiMetadataValue::try_from(b"hello-world").unwrap()
568 );
569 }
570 }
571
572 impl FromStr for MetadataValue<Ascii> {
573 type Err = InvalidMetadataValue;
574
575 #[inline]
from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err>576 fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> {
577 HeaderValue::from_str(s)
578 .map(|value| MetadataValue {
579 inner: value,
580 phantom: PhantomData,
581 })
582 .map_err(|_| InvalidMetadataValue::new())
583 }
584 }
585
586 impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
587 #[inline]
from(value: MetadataValue<VE>) -> Bytes588 fn from(value: MetadataValue<VE>) -> Bytes {
589 Bytes::copy_from_slice(value.inner.as_bytes())
590 }
591 }
592
593 impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
594 #[inline]
from(t: &'a MetadataValue<VE>) -> Self595 fn from(t: &'a MetadataValue<VE>) -> Self {
596 t.clone()
597 }
598 }
599
600 // ===== ToStrError =====
601
602 impl ToStrError {
new() -> Self603 pub(crate) fn new() -> Self {
604 ToStrError { _priv: () }
605 }
606 }
607
608 impl fmt::Display for ToStrError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result609 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610 f.write_str("failed to convert metadata to a str")
611 }
612 }
613
614 impl Error for ToStrError {}
615
616 impl Hash for MetadataValue<Ascii> {
hash<H: Hasher>(&self, state: &mut H)617 fn hash<H: Hasher>(&self, state: &mut H) {
618 self.inner.hash(state)
619 }
620 }
621
622 impl Hash for MetadataValue<Binary> {
hash<H: Hasher>(&self, state: &mut H)623 fn hash<H: Hasher>(&self, state: &mut H) {
624 match self.to_bytes() {
625 Ok(b) => b.hash(state),
626 Err(e) => e.hash(state),
627 }
628 }
629 }
630
631 // ===== PartialEq / PartialOrd =====
632
633 impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
634 #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool635 fn eq(&self, other: &MetadataValue<VE>) -> bool {
636 // Note: Different binary strings that after base64 decoding
637 // will count as the same value for Binary values. Also,
638 // different invalid base64 values count as equal for Binary
639 // values.
640 VE::values_equal(&self.inner, &other.inner)
641 }
642 }
643
644 impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
645
646 impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
647 #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>648 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
649 Some(self.cmp(other))
650 }
651 }
652
653 impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
654 #[inline]
cmp(&self, other: &Self) -> cmp::Ordering655 fn cmp(&self, other: &Self) -> cmp::Ordering {
656 self.inner.cmp(&other.inner)
657 }
658 }
659
660 impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
661 #[inline]
eq(&self, other: &str) -> bool662 fn eq(&self, other: &str) -> bool {
663 VE::equals(&self.inner, other.as_bytes())
664 }
665 }
666
667 impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
668 #[inline]
eq(&self, other: &[u8]) -> bool669 fn eq(&self, other: &[u8]) -> bool {
670 VE::equals(&self.inner, other)
671 }
672 }
673
674 impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
675 #[inline]
partial_cmp(&self, other: &str) -> Option<cmp::Ordering>676 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
677 self.inner.partial_cmp(other.as_bytes())
678 }
679 }
680
681 impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
682 #[inline]
partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering>683 fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
684 self.inner.partial_cmp(other)
685 }
686 }
687
688 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
689 #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool690 fn eq(&self, other: &MetadataValue<VE>) -> bool {
691 *other == *self
692 }
693 }
694
695 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
696 #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool697 fn eq(&self, other: &MetadataValue<VE>) -> bool {
698 *other == *self
699 }
700 }
701
702 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
703 #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>704 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
705 self.as_bytes().partial_cmp(other.inner.as_bytes())
706 }
707 }
708
709 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
710 #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>711 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
712 self.partial_cmp(other.inner.as_bytes())
713 }
714 }
715
716 impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
717 #[inline]
eq(&self, other: &String) -> bool718 fn eq(&self, other: &String) -> bool {
719 *self == other[..]
720 }
721 }
722
723 impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
724 #[inline]
partial_cmp(&self, other: &String) -> Option<cmp::Ordering>725 fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
726 self.inner.partial_cmp(other.as_bytes())
727 }
728 }
729
730 impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
731 #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool732 fn eq(&self, other: &MetadataValue<VE>) -> bool {
733 *other == *self
734 }
735 }
736
737 impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
738 #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>739 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
740 self.as_bytes().partial_cmp(other.inner.as_bytes())
741 }
742 }
743
744 impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a MetadataValue<VE> {
745 #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool746 fn eq(&self, other: &MetadataValue<VE>) -> bool {
747 **self == *other
748 }
749 }
750
751 impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a MetadataValue<VE> {
752 #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>753 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
754 (**self).partial_cmp(other)
755 }
756 }
757
758 impl<'a, VE: ValueEncoding, T: ?Sized> PartialEq<&'a T> for MetadataValue<VE>
759 where
760 MetadataValue<VE>: PartialEq<T>,
761 {
762 #[inline]
eq(&self, other: &&'a T) -> bool763 fn eq(&self, other: &&'a T) -> bool {
764 *self == **other
765 }
766 }
767
768 impl<'a, VE: ValueEncoding, T: ?Sized> PartialOrd<&'a T> for MetadataValue<VE>
769 where
770 MetadataValue<VE>: PartialOrd<T>,
771 {
772 #[inline]
partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering>773 fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
774 self.partial_cmp(*other)
775 }
776 }
777
778 impl<'a, VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &'a str {
779 #[inline]
eq(&self, other: &MetadataValue<VE>) -> bool780 fn eq(&self, other: &MetadataValue<VE>) -> bool {
781 *other == *self
782 }
783 }
784
785 impl<'a, VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &'a str {
786 #[inline]
partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering>787 fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
788 self.as_bytes().partial_cmp(other.inner.as_bytes())
789 }
790 }
791
792 #[test]
test_debug()793 fn test_debug() {
794 let cases = &[
795 ("hello", "\"hello\""),
796 ("hello \"world\"", "\"hello \\\"world\\\"\""),
797 ("\u{7FFF}hello", "\"\\xe7\\xbf\\xbfhello\""),
798 ];
799
800 for &(value, expected) in cases {
801 let val = AsciiMetadataValue::try_from(value.as_bytes()).unwrap();
802 let actual = format!("{:?}", val);
803 assert_eq!(expected, actual);
804 }
805
806 let mut sensitive = AsciiMetadataValue::from_static("password");
807 sensitive.set_sensitive(true);
808 assert_eq!("Sensitive", format!("{:?}", sensitive));
809 }
810
811 #[test]
test_is_empty()812 fn test_is_empty() {
813 fn from_str<VE: ValueEncoding>(s: &str) -> MetadataValue<VE> {
814 MetadataValue::<VE>::unchecked_from_header_value(s.parse().unwrap())
815 }
816
817 assert!(from_str::<Ascii>("").is_empty());
818 assert!(from_str::<Binary>("").is_empty());
819 assert!(!from_str::<Ascii>("a").is_empty());
820 assert!(!from_str::<Binary>("a").is_empty());
821 assert!(!from_str::<Ascii>("=").is_empty());
822 assert!(from_str::<Binary>("=").is_empty());
823 assert!(!from_str::<Ascii>("===").is_empty());
824 assert!(from_str::<Binary>("===").is_empty());
825 assert!(!from_str::<Ascii>("=====").is_empty());
826 assert!(from_str::<Binary>("=====").is_empty());
827 }
828
829 #[test]
test_from_shared_base64_encodes()830 fn test_from_shared_base64_encodes() {
831 let value = BinaryMetadataValue::try_from(Bytes::from_static(b"Hello")).unwrap();
832 assert_eq!(value.as_encoded_bytes(), b"SGVsbG8");
833 }
834
835 #[test]
test_value_eq_value()836 fn test_value_eq_value() {
837 type BMV = BinaryMetadataValue;
838 type AMV = AsciiMetadataValue;
839
840 assert_eq!(AMV::from_static("abc"), AMV::from_static("abc"));
841 assert_ne!(AMV::from_static("abc"), AMV::from_static("ABC"));
842
843 assert_eq!(BMV::from_bytes(b"abc"), BMV::from_bytes(b"abc"));
844 assert_ne!(BMV::from_bytes(b"abc"), BMV::from_bytes(b"ABC"));
845
846 // Padding is ignored.
847 assert_eq!(
848 BMV::from_static("SGVsbG8hIQ=="),
849 BMV::from_static("SGVsbG8hIQ")
850 );
851 // Invalid values are all just invalid from this point of view.
852 unsafe {
853 assert_eq!(
854 BMV::from_shared_unchecked(Bytes::from_static(b"..{}")),
855 BMV::from_shared_unchecked(Bytes::from_static(b"{}.."))
856 );
857 }
858 }
859
860 #[test]
test_value_eq_str()861 fn test_value_eq_str() {
862 type BMV = BinaryMetadataValue;
863 type AMV = AsciiMetadataValue;
864
865 assert_eq!(AMV::from_static("abc"), "abc");
866 assert_ne!(AMV::from_static("abc"), "ABC");
867 assert_eq!("abc", AMV::from_static("abc"));
868 assert_ne!("ABC", AMV::from_static("abc"));
869
870 assert_eq!(BMV::from_bytes(b"abc"), "abc");
871 assert_ne!(BMV::from_bytes(b"abc"), "ABC");
872 assert_eq!("abc", BMV::from_bytes(b"abc"));
873 assert_ne!("ABC", BMV::from_bytes(b"abc"));
874
875 // Padding is ignored.
876 assert_eq!(BMV::from_static("SGVsbG8hIQ=="), "Hello!!");
877 assert_eq!("Hello!!", BMV::from_static("SGVsbG8hIQ=="));
878 }
879
880 #[test]
test_value_eq_bytes()881 fn test_value_eq_bytes() {
882 type BMV = BinaryMetadataValue;
883 type AMV = AsciiMetadataValue;
884
885 assert_eq!(AMV::from_static("abc"), "abc".as_bytes());
886 assert_ne!(AMV::from_static("abc"), "ABC".as_bytes());
887 assert_eq!(*"abc".as_bytes(), AMV::from_static("abc"));
888 assert_ne!(*"ABC".as_bytes(), AMV::from_static("abc"));
889
890 assert_eq!(*"abc".as_bytes(), BMV::from_bytes(b"abc"));
891 assert_ne!(*"ABC".as_bytes(), BMV::from_bytes(b"abc"));
892
893 // Padding is ignored.
894 assert_eq!(BMV::from_static("SGVsbG8hIQ=="), "Hello!!".as_bytes());
895 assert_eq!(*"Hello!!".as_bytes(), BMV::from_static("SGVsbG8hIQ=="));
896 }
897
898 #[test]
test_ascii_value_hash()899 fn test_ascii_value_hash() {
900 use std::collections::hash_map::DefaultHasher;
901 type AMV = AsciiMetadataValue;
902
903 fn hash(value: AMV) -> u64 {
904 let mut hasher = DefaultHasher::new();
905 value.hash(&mut hasher);
906 hasher.finish()
907 }
908
909 let value1 = AMV::from_static("abc");
910 let value2 = AMV::from_static("abc");
911 assert_eq!(value1, value2);
912 assert_eq!(hash(value1), hash(value2));
913
914 let value1 = AMV::from_static("abc");
915 let value2 = AMV::from_static("xyz");
916
917 assert_ne!(value1, value2);
918 assert_ne!(hash(value1), hash(value2));
919 }
920
921 #[test]
test_valid_binary_value_hash()922 fn test_valid_binary_value_hash() {
923 use std::collections::hash_map::DefaultHasher;
924 type BMV = BinaryMetadataValue;
925
926 fn hash(value: BMV) -> u64 {
927 let mut hasher = DefaultHasher::new();
928 value.hash(&mut hasher);
929 hasher.finish()
930 }
931
932 let value1 = BMV::from_bytes(b"abc");
933 let value2 = BMV::from_bytes(b"abc");
934 assert_eq!(value1, value2);
935 assert_eq!(hash(value1), hash(value2));
936
937 let value1 = BMV::from_bytes(b"abc");
938 let value2 = BMV::from_bytes(b"xyz");
939 assert_ne!(value1, value2);
940 assert_ne!(hash(value1), hash(value2));
941 }
942
943 #[test]
test_invalid_binary_value_hash()944 fn test_invalid_binary_value_hash() {
945 use std::collections::hash_map::DefaultHasher;
946 type BMV = BinaryMetadataValue;
947
948 fn hash(value: BMV) -> u64 {
949 let mut hasher = DefaultHasher::new();
950 value.hash(&mut hasher);
951 hasher.finish()
952 }
953
954 unsafe {
955 let value1 = BMV::from_shared_unchecked(Bytes::from_static(b"..{}"));
956 let value2 = BMV::from_shared_unchecked(Bytes::from_static(b"{}.."));
957 assert_eq!(value1, value2);
958 assert_eq!(hash(value1), hash(value2));
959 }
960
961 unsafe {
962 let valid = BMV::from_bytes(b"abc");
963 let invalid = BMV::from_shared_unchecked(Bytes::from_static(b"{}.."));
964 assert_ne!(valid, invalid);
965 assert_ne!(hash(valid), hash(invalid));
966 }
967 }
968