Coverage Report

Created: 2025-11-16 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tonic-0.13.0/src/metadata/value.rs
Line
Count
Source
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]
71
0
    pub fn from_static(src: &'static str) -> Self {
72
0
        MetadataValue {
73
0
            inner: VE::from_static(src),
74
0
            phantom: PhantomData,
75
0
        }
76
0
    }
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]
87
0
    pub unsafe fn from_shared_unchecked(src: Bytes) -> Self {
88
0
        MetadataValue {
89
0
            inner: HeaderValue::from_maybe_shared_unchecked(src),
90
0
            phantom: PhantomData,
91
0
        }
92
0
    }
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]
107
0
    pub fn is_empty(&self) -> bool {
108
0
        VE::is_empty(self.inner.as_bytes())
109
0
    }
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]
129
0
    pub fn to_bytes(&self) -> Result<Bytes, InvalidMetadataValueBytes> {
130
0
        VE::decode(self.inner.as_bytes())
131
0
    }
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]
148
0
    pub fn set_sensitive(&mut self, val: bool) {
149
0
        self.inner.set_sensitive(val);
150
0
    }
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]
174
0
    pub fn is_sensitive(&self) -> bool {
175
0
        self.inner.is_sensitive()
176
0
    }
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]
195
0
    pub fn as_encoded_bytes(&self) -> &[u8] {
196
0
        self.inner.as_bytes()
197
0
    }
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]
203
0
    pub(crate) fn unchecked_from_header_value(value: HeaderValue) -> Self {
204
0
        MetadataValue {
205
0
            inner: value,
206
0
            phantom: PhantomData,
207
0
        }
208
0
    }
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]
214
0
    pub(crate) fn unchecked_from_header_value_ref(header_value: &HeaderValue) -> &Self {
215
0
        unsafe { &*(header_value as *const HeaderValue as *const Self) }
216
0
    }
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii>>::unchecked_from_header_value_ref
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Binary>>::unchecked_from_header_value_ref
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]
222
0
    pub(crate) fn unchecked_from_mut_header_value_ref(header_value: &mut HeaderValue) -> &mut Self {
223
0
        unsafe { &mut *(header_value as *mut HeaderValue as *mut Self) }
224
0
    }
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii>>::unchecked_from_mut_header_value_ref
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Binary>>::unchecked_from_mut_header_value_ref
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]
255
0
    fn try_from(src: &[u8]) -> Result<Self, Self::Error> {
256
0
        VE::from_bytes(src).map(|value| MetadataValue {
257
0
            inner: value,
258
0
            phantom: PhantomData,
259
0
        })
260
0
    }
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]
291
0
    fn try_from(src: &[u8; N]) -> Result<Self, Self::Error> {
292
0
        Self::try_from(src.as_ref())
293
0
    }
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]
310
0
    fn try_from(src: Bytes) -> Result<Self, Self::Error> {
311
0
        VE::from_shared(src).map(|value| MetadataValue {
312
0
            inner: value,
313
0
            phantom: PhantomData,
314
0
        })
315
0
    }
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]
332
0
    fn try_from(src: Vec<u8>) -> Result<Self, Self::Error> {
333
0
        Self::try_from(src.as_slice())
334
0
    }
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]
347
0
    fn try_from(s: &'a str) -> Result<Self, Self::Error> {
348
0
        s.parse()
349
0
    }
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]
362
0
    fn try_from(s: &'a String) -> Result<Self, Self::Error> {
363
0
        s.parse()
364
0
    }
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]
377
0
    fn try_from(s: String) -> Result<Self, Self::Error> {
378
0
        s.parse()
379
0
    }
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]
396
0
    pub fn from_key<KeyVE: ValueEncoding>(key: MetadataKey<KeyVE>) -> Self {
397
0
        key.into()
398
0
    }
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]
415
0
    pub fn len(&self) -> usize {
416
0
        self.inner.len()
417
0
    }
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
    /// ```
432
0
    pub fn to_str(&self) -> Result<&str, ToStrError> {
433
0
        self.inner.to_str().map_err(|_| ToStrError::new())
434
0
    }
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]
447
0
    pub fn as_bytes(&self) -> &[u8] {
448
0
        self.inner.as_bytes()
449
0
    }
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]
463
0
    pub fn from_bytes(src: &[u8]) -> Self {
464
        // Only the Ascii version of try_from can fail.
465
0
        Self::try_from(src).unwrap()
466
0
    }
467
}
468
469
impl<VE: ValueEncoding> AsRef<[u8]> for MetadataValue<VE> {
470
    #[inline]
471
0
    fn as_ref(&self) -> &[u8] {
472
0
        self.inner.as_ref()
473
0
    }
474
}
475
476
impl<VE: ValueEncoding> fmt::Debug for MetadataValue<VE> {
477
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478
0
        VE::fmt(&self.inner, f)
479
0
    }
480
}
481
482
impl<KeyVE: ValueEncoding> From<MetadataKey<KeyVE>> for MetadataValue<Ascii> {
483
    #[inline]
484
0
    fn from(h: MetadataKey<KeyVE>) -> MetadataValue<Ascii> {
485
0
        MetadataValue {
486
0
            inner: h.inner.into(),
487
0
            phantom: PhantomData,
488
0
        }
489
0
    }
490
}
491
492
macro_rules! from_integers {
493
    ($($name:ident: $t:ident => $max_len:expr),*) => {$(
494
        impl From<$t> for MetadataValue<Ascii> {
495
0
            fn from(num: $t) -> MetadataValue<Ascii> {
496
0
                MetadataValue {
497
0
                    inner: HeaderValue::from(num),
498
0
                    phantom: PhantomData,
499
0
                }
500
0
            }
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<u16>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<i16>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<u32>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<i32>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<u64>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<i64>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<usize>>::from
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::convert::From<isize>>::from
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]
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]
572
0
    fn from_str(s: &str) -> Result<MetadataValue<Ascii>, Self::Err> {
573
0
        HeaderValue::from_str(s)
574
0
            .map(|value| MetadataValue {
575
0
                inner: value,
576
0
                phantom: PhantomData,
577
0
            })
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#0}
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#0}
578
0
            .map_err(|_| InvalidMetadataValue::new())
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#1}
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str::{closure#1}
579
0
    }
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str
Unexecuted instantiation: <tonic::metadata::value::MetadataValue<tonic::metadata::encoding::Ascii> as core::str::traits::FromStr>::from_str
580
}
581
582
impl<VE: ValueEncoding> From<MetadataValue<VE>> for Bytes {
583
    #[inline]
584
0
    fn from(value: MetadataValue<VE>) -> Bytes {
585
0
        Bytes::copy_from_slice(value.inner.as_bytes())
586
0
    }
587
}
588
589
impl<'a, VE: ValueEncoding> From<&'a MetadataValue<VE>> for MetadataValue<VE> {
590
    #[inline]
591
0
    fn from(t: &'a MetadataValue<VE>) -> Self {
592
0
        t.clone()
593
0
    }
594
}
595
596
// ===== ToStrError =====
597
598
impl ToStrError {
599
0
    pub(crate) fn new() -> Self {
600
0
        ToStrError { _priv: () }
601
0
    }
602
}
603
604
impl fmt::Display for ToStrError {
605
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606
0
        f.write_str("failed to convert metadata to a str")
607
0
    }
608
}
609
610
impl Error for ToStrError {}
611
612
impl Hash for MetadataValue<Ascii> {
613
0
    fn hash<H: Hasher>(&self, state: &mut H) {
614
0
        self.inner.hash(state)
615
0
    }
616
}
617
618
impl Hash for MetadataValue<Binary> {
619
0
    fn hash<H: Hasher>(&self, state: &mut H) {
620
0
        match self.to_bytes() {
621
0
            Ok(b) => b.hash(state),
622
0
            Err(e) => e.hash(state),
623
        }
624
0
    }
625
}
626
627
// ===== PartialEq / PartialOrd =====
628
629
impl<VE: ValueEncoding> PartialEq for MetadataValue<VE> {
630
    #[inline]
631
0
    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
0
        VE::values_equal(&self.inner, &other.inner)
637
0
    }
638
}
639
640
impl<VE: ValueEncoding> Eq for MetadataValue<VE> {}
641
642
impl<VE: ValueEncoding> PartialOrd for MetadataValue<VE> {
643
    #[inline]
644
0
    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
645
0
        Some(self.cmp(other))
646
0
    }
647
}
648
649
impl<VE: ValueEncoding> Ord for MetadataValue<VE> {
650
    #[inline]
651
0
    fn cmp(&self, other: &Self) -> cmp::Ordering {
652
0
        self.inner.cmp(&other.inner)
653
0
    }
654
}
655
656
impl<VE: ValueEncoding> PartialEq<str> for MetadataValue<VE> {
657
    #[inline]
658
0
    fn eq(&self, other: &str) -> bool {
659
0
        VE::equals(&self.inner, other.as_bytes())
660
0
    }
661
}
662
663
impl<VE: ValueEncoding> PartialEq<[u8]> for MetadataValue<VE> {
664
    #[inline]
665
0
    fn eq(&self, other: &[u8]) -> bool {
666
0
        VE::equals(&self.inner, other)
667
0
    }
668
}
669
670
impl<VE: ValueEncoding> PartialOrd<str> for MetadataValue<VE> {
671
    #[inline]
672
0
    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
673
0
        self.inner.partial_cmp(other.as_bytes())
674
0
    }
675
}
676
677
impl<VE: ValueEncoding> PartialOrd<[u8]> for MetadataValue<VE> {
678
    #[inline]
679
0
    fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
680
0
        self.inner.partial_cmp(other)
681
0
    }
682
}
683
684
impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for str {
685
    #[inline]
686
0
    fn eq(&self, other: &MetadataValue<VE>) -> bool {
687
0
        *other == *self
688
0
    }
689
}
690
691
impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for [u8] {
692
    #[inline]
693
0
    fn eq(&self, other: &MetadataValue<VE>) -> bool {
694
0
        *other == *self
695
0
    }
696
}
697
698
impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for str {
699
    #[inline]
700
0
    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
701
0
        self.as_bytes().partial_cmp(other.inner.as_bytes())
702
0
    }
703
}
704
705
impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for [u8] {
706
    #[inline]
707
0
    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
708
0
        self.partial_cmp(other.inner.as_bytes())
709
0
    }
710
}
711
712
impl<VE: ValueEncoding> PartialEq<String> for MetadataValue<VE> {
713
    #[inline]
714
0
    fn eq(&self, other: &String) -> bool {
715
0
        *self == other[..]
716
0
    }
717
}
718
719
impl<VE: ValueEncoding> PartialOrd<String> for MetadataValue<VE> {
720
    #[inline]
721
0
    fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
722
0
        self.inner.partial_cmp(other.as_bytes())
723
0
    }
724
}
725
726
impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for String {
727
    #[inline]
728
0
    fn eq(&self, other: &MetadataValue<VE>) -> bool {
729
0
        *other == *self
730
0
    }
731
}
732
733
impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for String {
734
    #[inline]
735
0
    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
736
0
        self.as_bytes().partial_cmp(other.inner.as_bytes())
737
0
    }
738
}
739
740
impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &MetadataValue<VE> {
741
    #[inline]
742
0
    fn eq(&self, other: &MetadataValue<VE>) -> bool {
743
0
        **self == *other
744
0
    }
745
}
746
747
impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &MetadataValue<VE> {
748
    #[inline]
749
0
    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
750
0
        (**self).partial_cmp(other)
751
0
    }
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]
759
0
    fn eq(&self, other: &&'a T) -> bool {
760
0
        *self == **other
761
0
    }
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]
769
0
    fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
770
0
        self.partial_cmp(*other)
771
0
    }
772
}
773
774
impl<VE: ValueEncoding> PartialEq<MetadataValue<VE>> for &str {
775
    #[inline]
776
0
    fn eq(&self, other: &MetadataValue<VE>) -> bool {
777
0
        *other == *self
778
0
    }
779
}
780
781
impl<VE: ValueEncoding> PartialOrd<MetadataValue<VE>> for &str {
782
    #[inline]
783
0
    fn partial_cmp(&self, other: &MetadataValue<VE>) -> Option<cmp::Ordering> {
784
0
        self.as_bytes().partial_cmp(other.inner.as_bytes())
785
0
    }
786
}
787
788
#[test]
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]
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]
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]
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]
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]
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]
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]
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]
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
}