use bytes::{BufMut, Bytes, BytesMut};
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
pub enum DecodeError {
#[error("packet parsing failed")]
InvalidPacketError,
#[error("{field} was {value:x}, which is not known")]
ConstraintOutOfBounds { field: &'static str, value: u64 },
#[error("Got {actual:x}, expected {expected:x}")]
InvalidFixedValue { expected: u64, actual: u64 },
#[error("when parsing {obj} needed length of {wanted} but got {got}")]
InvalidLengthError { obj: &'static str, wanted: usize, got: usize },
#[error("array size ({array} bytes) is not a multiple of the element size ({element} bytes)")]
InvalidArraySize { array: usize, element: usize },
#[error("Due to size restrictions a struct could not be parsed.")]
ImpossibleStructError,
#[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
InvalidEnumValueError {
obj: &'static str,
field: &'static str,
value: u64,
type_: &'static str,
},
#[error("invalid field {packet}::{field} value, {expected} != {actual}")]
InvalidFieldValue {
packet: &'static str,
field: &'static str,
expected: &'static str,
actual: String,
},
#[error("expected child {expected}, got {actual}")]
InvalidChildError { expected: &'static str, actual: String },
#[error("packet has trailing bytes")]
TrailingBytes,
#[error("packet has trailing bytes inside {obj}.{field} array")]
TrailingBytesInArray { obj: &'static str, field: &'static str },
}
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
pub enum EncodeError {
#[error(
"the size of {packet}::{field} ({size}) is outside the range of valid values 0..{maximum_size}"
)]
SizeOverflow { packet: &'static str, field: &'static str, size: usize, maximum_size: usize },
#[error(
"the count of {packet}::{field} ({count}) is outside the range of valid values 0..{maximum_count}"
)]
CountOverflow { packet: &'static str, field: &'static str, count: usize, maximum_count: usize },
#[error(
"the value of {packet}::{field} ({value}) is outside the range of valid values 0..{maximum_value}"
)]
InvalidScalarValue { packet: &'static str, field: &'static str, value: u64, maximum_value: u64 },
#[error(
"{packet}.{field}[{element_index}] size is {size}, but {expected_size} was expected (size of {packet}.{field}[0])"
)]
InvalidArrayElementSize {
packet: &'static str,
field: &'static str,
size: usize,
expected_size: usize,
element_index: usize,
},
#[error("{packet}.{field} value cannot be uniquely determined")]
InconsistentConditionValue { packet: &'static str, field: &'static str },
}
pub trait Packet: Sized {
fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError>;
fn decode_mut(buf: &mut &[u8]) -> Result<Self, DecodeError> {
let (packet, remaining) = Self::decode(buf)?;
*buf = remaining;
Ok(packet)
}
fn decode_full(buf: &[u8]) -> Result<Self, DecodeError> {
let (packet, remaining) = Self::decode(buf)?;
if remaining.is_empty() { Ok(packet) } else { Err(DecodeError::TrailingBytes) }
}
fn encoded_len(&self) -> usize;
fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError>;
fn encode_to_vec(&self) -> Result<Vec<u8>, EncodeError> {
let mut buf = Vec::with_capacity(self.encoded_len());
self.encode(&mut buf)?;
Ok(buf)
}
fn encode_to_bytes(&self) -> Result<Bytes, EncodeError> {
let mut buf = BytesMut::with_capacity(self.encoded_len());
self.encode(&mut buf)?;
Ok(buf.freeze())
}
}