1 use base64::Engine as _; 2 use bytes::Bytes; 3 use http::header::HeaderValue; 4 use std::error::Error; 5 use std::fmt; 6 use std::hash::Hash; 7 8 /// A possible error when converting a `MetadataValue` from a string or byte 9 /// slice. 10 #[derive(Debug, Hash)] 11 pub struct InvalidMetadataValue { 12 _priv: (), 13 } 14 15 mod value_encoding { 16 use super::InvalidMetadataValueBytes; 17 use bytes::Bytes; 18 use http::header::HeaderValue; 19 use std::fmt; 20 21 pub trait Sealed { 22 #[doc(hidden)] is_empty(value: &[u8]) -> bool23 fn is_empty(value: &[u8]) -> bool; 24 25 #[doc(hidden)] from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>26 fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>; 27 28 #[doc(hidden)] from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>29 fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>; 30 31 #[doc(hidden)] from_static(value: &'static str) -> HeaderValue32 fn from_static(value: &'static str) -> HeaderValue; 33 34 #[doc(hidden)] decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>35 fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>; 36 37 #[doc(hidden)] equals(a: &HeaderValue, b: &[u8]) -> bool38 fn equals(a: &HeaderValue, b: &[u8]) -> bool; 39 40 #[doc(hidden)] values_equal(a: &HeaderValue, b: &HeaderValue) -> bool41 fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool; 42 43 #[doc(hidden)] fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result44 fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result; 45 } 46 } 47 48 pub trait ValueEncoding: Clone + Eq + PartialEq + Hash + self::value_encoding::Sealed { 49 /// Returns true if the provided key is valid for this ValueEncoding type. 50 /// For example, `Ascii::is_valid_key("a") == true`, 51 /// `Ascii::is_valid_key("a-bin") == false`. is_valid_key(key: &str) -> bool52 fn is_valid_key(key: &str) -> bool; 53 } 54 55 /// gRPC metadata values can be either ASCII strings or binary. Note that only 56 /// visible ASCII characters (32-127) are permitted. 57 /// This type should never be instantiated -- in fact, it's impossible 58 /// to, because there's no variants to instantiate. Instead, it's just used as 59 /// a type parameter for [`MetadataKey`] and [`MetadataValue`]. 60 /// 61 /// [`MetadataKey`]: struct.MetadataKey.html 62 /// [`MetadataValue`]: struct.MetadataValue.html 63 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 64 #[non_exhaustive] 65 pub enum Ascii {} 66 67 /// gRPC metadata values can be either ASCII strings or binary. 68 /// This type should never be instantiated -- in fact, it's impossible 69 /// to, because there's no variants to instantiate. Instead, it's just used as 70 /// a type parameter for [`MetadataKey`] and [`MetadataValue`]. 71 /// 72 /// [`MetadataKey`]: struct.MetadataKey.html 73 /// [`MetadataValue`]: struct.MetadataValue.html 74 #[derive(Clone, Debug, Eq, PartialEq, Hash)] 75 #[non_exhaustive] 76 pub enum Binary {} 77 78 // ===== impl ValueEncoding ===== 79 80 impl self::value_encoding::Sealed for Ascii { is_empty(value: &[u8]) -> bool81 fn is_empty(value: &[u8]) -> bool { 82 value.is_empty() 83 } 84 from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>85 fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> { 86 HeaderValue::from_bytes(value).map_err(|_| InvalidMetadataValueBytes::new()) 87 } 88 from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>89 fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> { 90 HeaderValue::from_maybe_shared(value).map_err(|_| InvalidMetadataValueBytes::new()) 91 } 92 from_static(value: &'static str) -> HeaderValue93 fn from_static(value: &'static str) -> HeaderValue { 94 HeaderValue::from_static(value) 95 } 96 decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>97 fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> { 98 Ok(Bytes::copy_from_slice(value)) 99 } 100 equals(a: &HeaderValue, b: &[u8]) -> bool101 fn equals(a: &HeaderValue, b: &[u8]) -> bool { 102 a.as_bytes() == b 103 } 104 values_equal(a: &HeaderValue, b: &HeaderValue) -> bool105 fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool { 106 a == b 107 } 108 fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result109 fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { 110 fmt::Debug::fmt(value, f) 111 } 112 } 113 114 impl ValueEncoding for Ascii { is_valid_key(key: &str) -> bool115 fn is_valid_key(key: &str) -> bool { 116 !Binary::is_valid_key(key) 117 } 118 } 119 120 impl self::value_encoding::Sealed for Binary { is_empty(value: &[u8]) -> bool121 fn is_empty(value: &[u8]) -> bool { 122 for c in value { 123 if *c != b'=' { 124 return false; 125 } 126 } 127 true 128 } 129 from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes>130 fn from_bytes(value: &[u8]) -> Result<HeaderValue, InvalidMetadataValueBytes> { 131 let encoded_value: String = crate::util::base64::STANDARD_NO_PAD.encode(value); 132 HeaderValue::from_maybe_shared(Bytes::from(encoded_value)) 133 .map_err(|_| InvalidMetadataValueBytes::new()) 134 } 135 from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes>136 fn from_shared(value: Bytes) -> Result<HeaderValue, InvalidMetadataValueBytes> { 137 Self::from_bytes(value.as_ref()) 138 } 139 from_static(value: &'static str) -> HeaderValue140 fn from_static(value: &'static str) -> HeaderValue { 141 if crate::util::base64::STANDARD.decode(value).is_err() { 142 panic!("Invalid base64 passed to from_static: {}", value); 143 } 144 unsafe { 145 // Because this is valid base64 this must be a valid HTTP header value, 146 // no need to check again by calling from_shared. 147 HeaderValue::from_maybe_shared_unchecked(Bytes::from_static(value.as_ref())) 148 } 149 } 150 decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes>151 fn decode(value: &[u8]) -> Result<Bytes, InvalidMetadataValueBytes> { 152 crate::util::base64::STANDARD 153 .decode(value) 154 .map(|bytes_vec| bytes_vec.into()) 155 .map_err(|_| InvalidMetadataValueBytes::new()) 156 } 157 equals(a: &HeaderValue, b: &[u8]) -> bool158 fn equals(a: &HeaderValue, b: &[u8]) -> bool { 159 if let Ok(decoded) = crate::util::base64::STANDARD.decode(a.as_bytes()) { 160 decoded == b 161 } else { 162 a.as_bytes() == b 163 } 164 } 165 values_equal(a: &HeaderValue, b: &HeaderValue) -> bool166 fn values_equal(a: &HeaderValue, b: &HeaderValue) -> bool { 167 match (Self::decode(a.as_bytes()), Self::decode(b.as_bytes())) { 168 (Ok(a), Ok(b)) => a == b, 169 (Err(_), Err(_)) => true, 170 _ => false, 171 } 172 } 173 fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result174 fn fmt(value: &HeaderValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { 175 if let Ok(decoded) = Self::decode(value.as_bytes()) { 176 write!(f, "{:?}", decoded) 177 } else { 178 write!(f, "b[invalid]{:?}", value) 179 } 180 } 181 } 182 183 impl ValueEncoding for Binary { is_valid_key(key: &str) -> bool184 fn is_valid_key(key: &str) -> bool { 185 key.ends_with("-bin") 186 } 187 } 188 189 // ===== impl InvalidMetadataValue ===== 190 191 impl InvalidMetadataValue { new() -> Self192 pub(crate) fn new() -> Self { 193 InvalidMetadataValue { _priv: () } 194 } 195 } 196 197 impl fmt::Display for InvalidMetadataValue { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 199 f.write_str("failed to parse metadata value") 200 } 201 } 202 203 impl Error for InvalidMetadataValue {} 204 205 /// A possible error when converting a `MetadataValue` from a string or byte 206 /// slice. 207 #[derive(Debug, Hash)] 208 pub struct InvalidMetadataValueBytes(InvalidMetadataValue); 209 210 // ===== impl InvalidMetadataValueBytes ===== 211 212 impl InvalidMetadataValueBytes { new() -> Self213 pub(crate) fn new() -> Self { 214 InvalidMetadataValueBytes(InvalidMetadataValue::new()) 215 } 216 } 217 218 impl fmt::Display for InvalidMetadataValueBytes { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 220 self.0.fmt(f) 221 } 222 } 223 224 impl Error for InvalidMetadataValueBytes {} 225