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