spetz commented on code in PR #2637:
URL: https://github.com/apache/iggy/pull/2637#discussion_r2745835916
##########
core/common/src/types/message/user_headers.rs:
##########
@@ -204,543 +303,765 @@ impl Display for HeaderKind {
}
}
-impl FromStr for HeaderValue {
- type Err = IggyError;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- Self::from(HeaderKind::String, s.as_bytes())
+impl<T> Display for HeaderField<T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}: ", self.kind)?;
+ write!(f, "{}", self.to_string_value())
}
}
-impl HeaderValue {
- /// Creates a new header value from the specified kind and value.
- /// The kind is parsed from the string representation.
- /// The value is parsed from the string representation.
- pub fn from_kind_str_and_value_str(kind: &str, value: &str) ->
Result<Self, IggyError> {
- let kind = HeaderKind::from_str(kind)?;
- Self::from_kind_and_value_str(kind, value)
- }
-
- /// Creates a new header value from the specified kind and value.
- /// The value is parsed from the string representation.
- pub fn from_kind_and_value_str(kind: HeaderKind, value: &str) ->
Result<Self, IggyError> {
- match kind {
- HeaderKind::Raw => Self::from_raw(value.as_bytes()),
- HeaderKind::String => Self::from_str(value),
- HeaderKind::Bool => {
- Self::from_bool(value.parse().map_err(|_|
IggyError::InvalidBooleanValue)?)
- }
- HeaderKind::Int8 => {
- Self::from_int8(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int16 => {
- Self::from_int16(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int32 => {
- Self::from_int32(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int64 => {
- Self::from_int64(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int128 => {
- Self::from_int128(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint8 => {
- Self::from_uint8(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint16 => {
- Self::from_uint16(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint32 => {
- Self::from_uint32(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint64 => {
- Self::from_uint64(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint128 => {
- Self::from_uint128(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Float32 => {
- Self::from_float32(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Float64 => {
- Self::from_float64(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- }
+impl<T> Hash for HeaderField<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.kind.hash(state);
+ self.value.hash(state);
}
- /// Creates a new header value from the specified raw bytes.
- pub fn from_raw(value: &[u8]) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Raw, value)
+}
+
+impl<T> FromStr for HeaderField<T> {
+ type Err = IggyError;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Self::try_from(s)
}
+}
- /// Returns the raw bytes of the header value.
+impl<T> HeaderField<T> {
pub fn as_raw(&self) -> Result<&[u8], IggyError> {
if self.kind != HeaderKind::Raw {
return Err(IggyError::InvalidHeaderValue);
}
-
Ok(&self.value)
}
- /// Returns the string representation of the header value.
pub fn as_str(&self) -> Result<&str, IggyError> {
if self.kind != HeaderKind::String {
return Err(IggyError::InvalidHeaderValue);
}
-
std::str::from_utf8(&self.value).map_err(|_| IggyError::InvalidUtf8)
}
- /// Creates a new header value from the specified string.
- pub fn from_bool(value: bool) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Bool, if value { &[1] } else { &[0] })
- }
-
- /// Returns the boolean representation of the header value.
pub fn as_bool(&self) -> Result<bool, IggyError> {
if self.kind != HeaderKind::Bool {
return Err(IggyError::InvalidHeaderValue);
}
-
match self.value[0] {
0 => Ok(false),
1 => Ok(true),
_ => Err(IggyError::InvalidHeaderValue),
}
}
- /// Creates a new header value from the specified boolean.
- pub fn from_int8(value: i8) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int8, &value.to_le_bytes())
- }
-
- /// Returns the i8 representation of the header value.
pub fn as_int8(&self) -> Result<i8, IggyError> {
if self.kind != HeaderKind::Int8 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i8::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i8.
- pub fn from_int16(value: i16) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int16, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i8::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i16 representation of the header value.
pub fn as_int16(&self) -> Result<i16, IggyError> {
if self.kind != HeaderKind::Int16 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i16::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i16.
- pub fn from_int32(value: i32) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int32, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i16::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i32 representation of the header value.
pub fn as_int32(&self) -> Result<i32, IggyError> {
if self.kind != HeaderKind::Int32 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i32::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i32.
- pub fn from_int64(value: i64) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int64, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i32::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i64 representation of the header value.
pub fn as_int64(&self) -> Result<i64, IggyError> {
if self.kind != HeaderKind::Int64 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i64::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i128.
- pub fn from_int128(value: i128) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int128, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i64::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i128 representation of the header value.
pub fn as_int128(&self) -> Result<i128, IggyError> {
if self.kind != HeaderKind::Int128 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i128::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified u8.
- pub fn from_uint8(value: u8) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint8, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i128::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the u8 representation of the header value.
pub fn as_uint8(&self) -> Result<u8, IggyError> {
if self.kind != HeaderKind::Uint8 {
return Err(IggyError::InvalidHeaderValue);
}
-
Ok(self.value[0])
}
- /// Creates a new header value from the specified u16.
- pub fn from_uint16(value: u16) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint16, &value.to_le_bytes())
- }
-
- /// Returns the u16 representation of the header value.
pub fn as_uint16(&self) -> Result<u16, IggyError> {
if self.kind != HeaderKind::Uint16 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u16::from_le_bytes(value.unwrap()))
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u16::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Creates a new header value from the specified u32.
- pub fn from_uint32(value: u32) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint32, &value.to_le_bytes())
- }
-
- /// Returns the u32 representation of the header value.
pub fn as_uint32(&self) -> Result<u32, IggyError> {
if self.kind != HeaderKind::Uint32 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u32::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified u64.
- pub fn from_uint64(value: u64) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint64, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u32::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the u64 representation of the header value.
pub fn as_uint64(&self) -> Result<u64, IggyError> {
if self.kind != HeaderKind::Uint64 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u64::from_le_bytes(value.unwrap()))
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u64::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Creates a new header value from the specified u128.
- pub fn from_uint128(value: u128) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint128, &value.to_le_bytes())
- }
-
- /// Returns the u128 representation of the header value.
pub fn as_uint128(&self) -> Result<u128, IggyError> {
if self.kind != HeaderKind::Uint128 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u128::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified f32.
- pub fn from_float32(value: f32) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Float32, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u128::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the f32 representation of the header value.
pub fn as_float32(&self) -> Result<f32, IggyError> {
if self.kind != HeaderKind::Float32 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(f32::from_le_bytes(value.unwrap()))
+ self.value
+ .as_ref()
+ .try_into()
+ .map(f32::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Creates a new header value from the specified f64.
- pub fn from_float64(value: f64) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Float64, &value.to_le_bytes())
- }
-
- /// Returns the f64 representation of the header value.
pub fn as_float64(&self) -> Result<f64, IggyError> {
if self.kind != HeaderKind::Float64 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(f64::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified kind and value.
- fn from(kind: HeaderKind, value: &[u8]) -> Result<Self, IggyError> {
- if value.is_empty() || value.len() > 255 {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(Self {
- kind,
- value: Bytes::from(value.to_vec()),
- })
+ self.value
+ .as_ref()
+ .try_into()
+ .map(f64::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the string representation of the header value without the kind.
- pub fn value_only_to_string(&self) -> String {
+ pub fn to_string_value(&self) -> String {
match self.kind {
HeaderKind::Raw => format!("{:?}", self.value),
- HeaderKind::String => format!("{}",
String::from_utf8_lossy(&self.value)),
+ HeaderKind::String =>
String::from_utf8_lossy(&self.value).to_string(),
HeaderKind::Bool => format!("{}", self.value[0] != 0),
HeaderKind::Int8 => format!(
"{}",
- i8::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i8::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int16 => format!(
"{}",
- i16::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i16::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int32 => format!(
"{}",
- i32::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i32::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int64 => format!(
"{}",
- i64::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i64::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int128 => format!(
"{}",
- i128::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i128::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint8 => format!(
"{}",
- u8::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u8::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint16 => format!(
"{}",
- u16::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u16::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint32 => format!(
"{}",
- u32::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u32::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint64 => format!(
"{}",
- u64::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u64::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint128 => format!(
"{}",
- u128::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u128::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Float32 => format!(
"{}",
- f32::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ f32::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Float64 => format!(
"{}",
- f64::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ f64::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
}
}
-}
-impl BytesSerializable for HashMap<HeaderKey, HeaderValue> {
- fn to_bytes(&self) -> Bytes {
- if self.is_empty() {
- return Bytes::new();
+ fn new_unchecked(kind: HeaderKind, value: &[u8]) -> Self {
+ Self {
+ kind,
+ value: Bytes::from(value.to_vec()),
+ _marker: PhantomData,
}
+ }
+}
- let mut bytes = BytesMut::new();
- for (key, value) in self {
- #[allow(clippy::cast_possible_truncation)]
- bytes.put_u32_le(key.0.len() as u32);
- bytes.put_slice(key.0.as_bytes());
- bytes.put_u8(value.kind.as_code());
- #[allow(clippy::cast_possible_truncation)]
- bytes.put_u32_le(value.value.len() as u32);
- bytes.put_slice(&value.value);
+impl<T> TryFrom<&str> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: &str) -> Result<Self, Self::Error> {
+ if value.is_empty() || value.len() > 255 {
+ return Err(IggyError::InvalidHeaderValue);
}
-
- bytes.freeze()
+ Ok(Self::new_unchecked(HeaderKind::String, value.as_bytes()))
}
+}
- fn from_bytes(bytes: Bytes) -> Result<Self, IggyError>
- where
- Self: Sized,
- {
- if bytes.is_empty() {
- return Ok(Self::new());
- }
+impl<T> TryFrom<String> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: String) -> Result<Self, Self::Error> {
+ Self::try_from(value.as_str())
+ }
+}
- let mut headers = Self::new();
- let mut position = 0;
- while position < bytes.len() {
- let key_length = u32::from_le_bytes(
- bytes[position..position + 4]
- .try_into()
- .map_err(|_| IggyError::InvalidNumberEncoding)?,
- ) as usize;
- if key_length == 0 || key_length > 255 {
- tracing::error!("Invalid header key length: {key_length}");
- return Err(IggyError::InvalidHeaderKey);
- }
- position += 4;
- let key = match String::from_utf8(bytes[position..position +
key_length].to_vec()) {
- Ok(k) => k,
- Err(e) => {
- tracing::error!("Invalid header key: {e}");
- return Err(IggyError::InvalidHeaderKey);
- }
- };
- position += key_length;
- let kind = HeaderKind::from_code(bytes[position])?;
- position += 1;
- let value_length = u32::from_le_bytes(
- bytes[position..position + 4]
- .try_into()
- .map_err(|_| IggyError::InvalidNumberEncoding)?,
- ) as usize;
- if value_length == 0 || value_length > 255 {
- tracing::error!("Invalid header value length: {value_length}");
- return Err(IggyError::InvalidHeaderValue);
- }
- position += 4;
- let value = bytes[position..position + value_length].to_vec();
- position += value_length;
- headers.insert(
- HeaderKey(key),
- HeaderValue {
- kind,
- value: Bytes::from(value),
- },
- );
+impl<T> TryFrom<&[u8]> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+ if value.is_empty() || value.len() > 255 {
+ return Err(IggyError::InvalidHeaderValue);
}
-
- Ok(headers)
+ Ok(Self::new_unchecked(HeaderKind::Raw, value))
}
}
Review Comment:
Good catch, fixed!
##########
core/common/src/types/message/user_headers.rs:
##########
@@ -204,543 +303,765 @@ impl Display for HeaderKind {
}
}
-impl FromStr for HeaderValue {
- type Err = IggyError;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- Self::from(HeaderKind::String, s.as_bytes())
+impl<T> Display for HeaderField<T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}: ", self.kind)?;
+ write!(f, "{}", self.to_string_value())
}
}
-impl HeaderValue {
- /// Creates a new header value from the specified kind and value.
- /// The kind is parsed from the string representation.
- /// The value is parsed from the string representation.
- pub fn from_kind_str_and_value_str(kind: &str, value: &str) ->
Result<Self, IggyError> {
- let kind = HeaderKind::from_str(kind)?;
- Self::from_kind_and_value_str(kind, value)
- }
-
- /// Creates a new header value from the specified kind and value.
- /// The value is parsed from the string representation.
- pub fn from_kind_and_value_str(kind: HeaderKind, value: &str) ->
Result<Self, IggyError> {
- match kind {
- HeaderKind::Raw => Self::from_raw(value.as_bytes()),
- HeaderKind::String => Self::from_str(value),
- HeaderKind::Bool => {
- Self::from_bool(value.parse().map_err(|_|
IggyError::InvalidBooleanValue)?)
- }
- HeaderKind::Int8 => {
- Self::from_int8(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int16 => {
- Self::from_int16(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int32 => {
- Self::from_int32(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int64 => {
- Self::from_int64(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Int128 => {
- Self::from_int128(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint8 => {
- Self::from_uint8(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint16 => {
- Self::from_uint16(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint32 => {
- Self::from_uint32(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint64 => {
- Self::from_uint64(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Uint128 => {
- Self::from_uint128(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Float32 => {
- Self::from_float32(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- HeaderKind::Float64 => {
- Self::from_float64(value.parse().map_err(|_|
IggyError::InvalidNumberValue)?)
- }
- }
+impl<T> Hash for HeaderField<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.kind.hash(state);
+ self.value.hash(state);
}
- /// Creates a new header value from the specified raw bytes.
- pub fn from_raw(value: &[u8]) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Raw, value)
+}
+
+impl<T> FromStr for HeaderField<T> {
+ type Err = IggyError;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Self::try_from(s)
}
+}
- /// Returns the raw bytes of the header value.
+impl<T> HeaderField<T> {
pub fn as_raw(&self) -> Result<&[u8], IggyError> {
if self.kind != HeaderKind::Raw {
return Err(IggyError::InvalidHeaderValue);
}
-
Ok(&self.value)
}
- /// Returns the string representation of the header value.
pub fn as_str(&self) -> Result<&str, IggyError> {
if self.kind != HeaderKind::String {
return Err(IggyError::InvalidHeaderValue);
}
-
std::str::from_utf8(&self.value).map_err(|_| IggyError::InvalidUtf8)
}
- /// Creates a new header value from the specified string.
- pub fn from_bool(value: bool) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Bool, if value { &[1] } else { &[0] })
- }
-
- /// Returns the boolean representation of the header value.
pub fn as_bool(&self) -> Result<bool, IggyError> {
if self.kind != HeaderKind::Bool {
return Err(IggyError::InvalidHeaderValue);
}
-
match self.value[0] {
0 => Ok(false),
1 => Ok(true),
_ => Err(IggyError::InvalidHeaderValue),
}
}
- /// Creates a new header value from the specified boolean.
- pub fn from_int8(value: i8) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int8, &value.to_le_bytes())
- }
-
- /// Returns the i8 representation of the header value.
pub fn as_int8(&self) -> Result<i8, IggyError> {
if self.kind != HeaderKind::Int8 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i8::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i8.
- pub fn from_int16(value: i16) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int16, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i8::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i16 representation of the header value.
pub fn as_int16(&self) -> Result<i16, IggyError> {
if self.kind != HeaderKind::Int16 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i16::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i16.
- pub fn from_int32(value: i32) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int32, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i16::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i32 representation of the header value.
pub fn as_int32(&self) -> Result<i32, IggyError> {
if self.kind != HeaderKind::Int32 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i32::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i32.
- pub fn from_int64(value: i64) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int64, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i32::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i64 representation of the header value.
pub fn as_int64(&self) -> Result<i64, IggyError> {
if self.kind != HeaderKind::Int64 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i64::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified i128.
- pub fn from_int128(value: i128) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Int128, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i64::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the i128 representation of the header value.
pub fn as_int128(&self) -> Result<i128, IggyError> {
if self.kind != HeaderKind::Int128 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(i128::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified u8.
- pub fn from_uint8(value: u8) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint8, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(i128::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the u8 representation of the header value.
pub fn as_uint8(&self) -> Result<u8, IggyError> {
if self.kind != HeaderKind::Uint8 {
return Err(IggyError::InvalidHeaderValue);
}
-
Ok(self.value[0])
}
- /// Creates a new header value from the specified u16.
- pub fn from_uint16(value: u16) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint16, &value.to_le_bytes())
- }
-
- /// Returns the u16 representation of the header value.
pub fn as_uint16(&self) -> Result<u16, IggyError> {
if self.kind != HeaderKind::Uint16 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u16::from_le_bytes(value.unwrap()))
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u16::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Creates a new header value from the specified u32.
- pub fn from_uint32(value: u32) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint32, &value.to_le_bytes())
- }
-
- /// Returns the u32 representation of the header value.
pub fn as_uint32(&self) -> Result<u32, IggyError> {
if self.kind != HeaderKind::Uint32 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u32::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified u64.
- pub fn from_uint64(value: u64) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint64, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u32::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the u64 representation of the header value.
pub fn as_uint64(&self) -> Result<u64, IggyError> {
if self.kind != HeaderKind::Uint64 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u64::from_le_bytes(value.unwrap()))
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u64::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Creates a new header value from the specified u128.
- pub fn from_uint128(value: u128) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Uint128, &value.to_le_bytes())
- }
-
- /// Returns the u128 representation of the header value.
pub fn as_uint128(&self) -> Result<u128, IggyError> {
if self.kind != HeaderKind::Uint128 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(u128::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified f32.
- pub fn from_float32(value: f32) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Float32, &value.to_le_bytes())
+ self.value
+ .as_ref()
+ .try_into()
+ .map(u128::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the f32 representation of the header value.
pub fn as_float32(&self) -> Result<f32, IggyError> {
if self.kind != HeaderKind::Float32 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(f32::from_le_bytes(value.unwrap()))
+ self.value
+ .as_ref()
+ .try_into()
+ .map(f32::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Creates a new header value from the specified f64.
- pub fn from_float64(value: f64) -> Result<Self, IggyError> {
- Self::from(HeaderKind::Float64, &value.to_le_bytes())
- }
-
- /// Returns the f64 representation of the header value.
pub fn as_float64(&self) -> Result<f64, IggyError> {
if self.kind != HeaderKind::Float64 {
return Err(IggyError::InvalidHeaderValue);
}
-
- let value = self.value.to_vec().try_into();
- if value.is_err() {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(f64::from_le_bytes(value.unwrap()))
- }
-
- /// Creates a new header value from the specified kind and value.
- fn from(kind: HeaderKind, value: &[u8]) -> Result<Self, IggyError> {
- if value.is_empty() || value.len() > 255 {
- return Err(IggyError::InvalidHeaderValue);
- }
-
- Ok(Self {
- kind,
- value: Bytes::from(value.to_vec()),
- })
+ self.value
+ .as_ref()
+ .try_into()
+ .map(f64::from_le_bytes)
+ .map_err(|_| IggyError::InvalidHeaderValue)
}
- /// Returns the string representation of the header value without the kind.
- pub fn value_only_to_string(&self) -> String {
+ pub fn to_string_value(&self) -> String {
match self.kind {
HeaderKind::Raw => format!("{:?}", self.value),
- HeaderKind::String => format!("{}",
String::from_utf8_lossy(&self.value)),
+ HeaderKind::String =>
String::from_utf8_lossy(&self.value).to_string(),
HeaderKind::Bool => format!("{}", self.value[0] != 0),
HeaderKind::Int8 => format!(
"{}",
- i8::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i8::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int16 => format!(
"{}",
- i16::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i16::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int32 => format!(
"{}",
- i32::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i32::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int64 => format!(
"{}",
- i64::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i64::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Int128 => format!(
"{}",
- i128::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ i128::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint8 => format!(
"{}",
- u8::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u8::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint16 => format!(
"{}",
- u16::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u16::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint32 => format!(
"{}",
- u32::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u32::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint64 => format!(
"{}",
- u64::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u64::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Uint128 => format!(
"{}",
- u128::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ u128::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Float32 => format!(
"{}",
- f32::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ f32::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
HeaderKind::Float64 => format!(
"{}",
- f64::from_le_bytes(self.value.to_vec().try_into().unwrap())
+ f64::from_le_bytes(self.value.as_ref().try_into().unwrap())
),
}
}
-}
-impl BytesSerializable for HashMap<HeaderKey, HeaderValue> {
- fn to_bytes(&self) -> Bytes {
- if self.is_empty() {
- return Bytes::new();
+ fn new_unchecked(kind: HeaderKind, value: &[u8]) -> Self {
+ Self {
+ kind,
+ value: Bytes::from(value.to_vec()),
+ _marker: PhantomData,
}
+ }
+}
- let mut bytes = BytesMut::new();
- for (key, value) in self {
- #[allow(clippy::cast_possible_truncation)]
- bytes.put_u32_le(key.0.len() as u32);
- bytes.put_slice(key.0.as_bytes());
- bytes.put_u8(value.kind.as_code());
- #[allow(clippy::cast_possible_truncation)]
- bytes.put_u32_le(value.value.len() as u32);
- bytes.put_slice(&value.value);
+impl<T> TryFrom<&str> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: &str) -> Result<Self, Self::Error> {
+ if value.is_empty() || value.len() > 255 {
+ return Err(IggyError::InvalidHeaderValue);
}
-
- bytes.freeze()
+ Ok(Self::new_unchecked(HeaderKind::String, value.as_bytes()))
}
+}
- fn from_bytes(bytes: Bytes) -> Result<Self, IggyError>
- where
- Self: Sized,
- {
- if bytes.is_empty() {
- return Ok(Self::new());
- }
+impl<T> TryFrom<String> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: String) -> Result<Self, Self::Error> {
+ Self::try_from(value.as_str())
+ }
+}
- let mut headers = Self::new();
- let mut position = 0;
- while position < bytes.len() {
- let key_length = u32::from_le_bytes(
- bytes[position..position + 4]
- .try_into()
- .map_err(|_| IggyError::InvalidNumberEncoding)?,
- ) as usize;
- if key_length == 0 || key_length > 255 {
- tracing::error!("Invalid header key length: {key_length}");
- return Err(IggyError::InvalidHeaderKey);
- }
- position += 4;
- let key = match String::from_utf8(bytes[position..position +
key_length].to_vec()) {
- Ok(k) => k,
- Err(e) => {
- tracing::error!("Invalid header key: {e}");
- return Err(IggyError::InvalidHeaderKey);
- }
- };
- position += key_length;
- let kind = HeaderKind::from_code(bytes[position])?;
- position += 1;
- let value_length = u32::from_le_bytes(
- bytes[position..position + 4]
- .try_into()
- .map_err(|_| IggyError::InvalidNumberEncoding)?,
- ) as usize;
- if value_length == 0 || value_length > 255 {
- tracing::error!("Invalid header value length: {value_length}");
- return Err(IggyError::InvalidHeaderValue);
- }
- position += 4;
- let value = bytes[position..position + value_length].to_vec();
- position += value_length;
- headers.insert(
- HeaderKey(key),
- HeaderValue {
- kind,
- value: Bytes::from(value),
- },
- );
+impl<T> TryFrom<&[u8]> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+ if value.is_empty() || value.len() > 255 {
+ return Err(IggyError::InvalidHeaderValue);
}
-
- Ok(headers)
+ Ok(Self::new_unchecked(HeaderKind::Raw, value))
}
}
-/// Returns the size in bytes of the specified headers.
-pub fn get_user_headers_size(headers: &Option<HashMap<HeaderKey,
HeaderValue>>) -> Option<u32> {
- let mut size = 0;
- if let Some(headers) = headers {
- for (key, value) in headers {
- size += 4 + key.as_str().len() as u32 + 1 + 4 + value.value.len()
as u32;
- }
+impl<T> TryFrom<Vec<u8>> for HeaderField<T> {
+ type Error = IggyError;
+ fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
+ Self::try_from(value.as_slice())
}
- Some(size)
}
-#[cfg(test)]
-mod tests {
- use super::*;
+impl<T> From<bool> for HeaderField<T> {
+ fn from(value: bool) -> Self {
+ Self::new_unchecked(HeaderKind::Bool, if value { &[1] } else { &[0] })
+ }
+}
- #[test]
- fn header_key_should_be_created_for_valid_value() {
- let value = "key-1";
- let header_key = HeaderKey::new(value);
- assert!(header_key.is_ok());
- assert_eq!(header_key.unwrap().0, value);
+impl<T> From<i8> for HeaderField<T> {
+ fn from(value: i8) -> Self {
+ Self::new_unchecked(HeaderKind::Int8, &value.to_le_bytes())
}
+}
- #[test]
- fn header_key_should_not_be_created_for_empty_value() {
- let value = "";
- let header_key = HeaderKey::new(value);
- assert!(header_key.is_err());
- let error = header_key.unwrap_err();
- assert_eq!(error.as_code(), IggyError::InvalidHeaderKey.as_code());
+impl<T> From<i16> for HeaderField<T> {
+ fn from(value: i16) -> Self {
+ Self::new_unchecked(HeaderKind::Int16, &value.to_le_bytes())
}
+}
- #[test]
- fn header_key_should_not_be_created_for_too_long_value() {
- let value = "a".repeat(256);
- let header_key = HeaderKey::new(&value);
- assert!(header_key.is_err());
- let error = header_key.unwrap_err();
- assert_eq!(error.as_code(), IggyError::InvalidHeaderKey.as_code());
+impl<T> From<i32> for HeaderField<T> {
+ fn from(value: i32) -> Self {
+ Self::new_unchecked(HeaderKind::Int32, &value.to_le_bytes())
}
+}
- #[test]
- fn header_value_should_not_be_created_for_empty_value() {
- let header_value = HeaderValue::from(HeaderKind::Raw, &[]);
- assert!(header_value.is_err());
- let error = header_value.unwrap_err();
- assert_eq!(error.as_code(), IggyError::InvalidHeaderValue.as_code());
+impl<T> From<i64> for HeaderField<T> {
+ fn from(value: i64) -> Self {
+ Self::new_unchecked(HeaderKind::Int64, &value.to_le_bytes())
}
+}
- #[test]
- fn header_value_should_not_be_created_for_too_long_value() {
- let value = b"a".repeat(256);
- let header_value = HeaderValue::from(HeaderKind::Raw, &value);
- assert!(header_value.is_err());
- let error = header_value.unwrap_err();
- assert_eq!(error.as_code(), IggyError::InvalidHeaderValue.as_code());
+impl<T> From<i128> for HeaderField<T> {
+ fn from(value: i128) -> Self {
+ Self::new_unchecked(HeaderKind::Int128, &value.to_le_bytes())
}
+}
- #[test]
- fn header_value_should_be_created_from_raw_bytes() {
- let value = b"Value 1";
- let header_value = HeaderValue::from_raw(value);
- assert!(header_value.is_ok());
- assert_eq!(header_value.unwrap().value.as_ref(), value);
+impl<T> From<u8> for HeaderField<T> {
+ fn from(value: u8) -> Self {
+ Self::new_unchecked(HeaderKind::Uint8, &value.to_le_bytes())
+ }
+}
+
+impl<T> From<u16> for HeaderField<T> {
+ fn from(value: u16) -> Self {
+ Self::new_unchecked(HeaderKind::Uint16, &value.to_le_bytes())
+ }
+}
+
+impl<T> From<u32> for HeaderField<T> {
+ fn from(value: u32) -> Self {
+ Self::new_unchecked(HeaderKind::Uint32, &value.to_le_bytes())
+ }
+}
+
+impl<T> From<u64> for HeaderField<T> {
+ fn from(value: u64) -> Self {
+ Self::new_unchecked(HeaderKind::Uint64, &value.to_le_bytes())
+ }
+}
+
+impl<T> From<u128> for HeaderField<T> {
+ fn from(value: u128) -> Self {
+ Self::new_unchecked(HeaderKind::Uint128, &value.to_le_bytes())
+ }
+}
+
+impl<T> From<f32> for HeaderField<T> {
+ fn from(value: f32) -> Self {
+ Self::new_unchecked(HeaderKind::Float32, &value.to_le_bytes())
+ }
+}
+
+impl<T> From<f64> for HeaderField<T> {
+ fn from(value: f64) -> Self {
+ Self::new_unchecked(HeaderKind::Float64, &value.to_le_bytes())
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for bool {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_bool()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for bool {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_bool()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for i8 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int8()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for i8 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int8()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for i16 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int16()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for i16 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int16()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for i32 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int32()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for i32 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int32()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for i64 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int64()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for i64 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int64()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for i128 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int128()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for i128 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_int128()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for u8 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint8()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for u8 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint8()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for u16 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint16()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for u16 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint16()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for u32 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint32()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for u32 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint32()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for u64 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint64()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for u64 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint64()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for u128 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint128()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for u128 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_uint128()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for f32 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_float32()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for f32 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_float32()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for f64 {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_float64()
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for f64 {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_float64()
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for String {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_str().map(|s| s.to_owned())
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for String {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_str().map(|s| s.to_owned())
+ }
+}
+
+impl<T> TryFrom<HeaderField<T>> for Vec<u8> {
+ type Error = IggyError;
+ fn try_from(field: HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_raw().map(|s| s.to_vec())
+ }
+}
+
+impl<T> TryFrom<&HeaderField<T>> for Vec<u8> {
+ type Error = IggyError;
+ fn try_from(field: &HeaderField<T>) -> Result<Self, Self::Error> {
+ field.as_raw().map(|s| s.to_vec())
+ }
+}
+
+impl BytesSerializable for HashMap<HeaderKey, HeaderValue> {
+ fn to_bytes(&self) -> Bytes {
+ if self.is_empty() {
+ return Bytes::new();
+ }
+
+ let mut bytes = BytesMut::new();
+ for (key, value) in self {
+ bytes.put_u8(key.kind.as_code());
+ #[allow(clippy::cast_possible_truncation)]
+ bytes.put_u32_le(key.value.len() as u32);
+ bytes.put_slice(&key.value);
+ bytes.put_u8(value.kind.as_code());
+ #[allow(clippy::cast_possible_truncation)]
+ bytes.put_u32_le(value.value.len() as u32);
+ bytes.put_slice(&value.value);
+ }
+
+ bytes.freeze()
+ }
+
+ fn from_bytes(bytes: Bytes) -> Result<Self, IggyError>
+ where
+ Self: Sized,
+ {
+ if bytes.is_empty() {
+ return Ok(Self::new());
+ }
+
+ let mut headers = Self::new();
+ let mut position = 0;
+ while position < bytes.len() {
+ let key_kind = HeaderKind::from_code(bytes[position])?;
+ position += 1;
+ let key_length = u32::from_le_bytes(
+ bytes[position..position + 4]
+ .try_into()
+ .map_err(|_| IggyError::InvalidNumberEncoding)?,
+ ) as usize;
+ if key_length == 0 || key_length > 255 {
+ tracing::error!("Invalid header key length: {key_length}");
+ return Err(IggyError::InvalidHeaderKey);
+ }
+ position += 4;
+ let key_value = bytes[position..position + key_length].to_vec();
Review Comment:
Right, also fixed
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]