Display for CheckedParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Parse(parse_error) => write!(f, "{}", parse_error),
Self::Size(size_error) => {
write!(f, "size check failed: {}", size_error)
}
}
}
}
impl From for CheckedParseError
{
fn from(value: P) -> Self {
Self::Parse(value)
}
}
/// Returned by [`CheckedParse::deserialize_checked`].
pub type CheckedParseResult<'a, Ctx, F> =
Result, CheckedParseError>>;
/// Extension trait for factories that ensures fixed size read.
pub trait CheckedParse<'a, Ctx: Context<'a>>: FixedSizeFactory<'a, Ctx> {
/// Verify proper read length using [`Deserializer::tell`].
fn deserialize_checked(
&self,
deserializer: &mut dyn Deserializer,
resolver: &Rc>,
addresses: &mut Addresses,
) -> CheckedParseResult<'a, Ctx, Self> {
let expected_size = self.size();
let start = deserializer.tell();
let result = self.deserialize(deserializer, resolver, addresses)?;
let end = deserializer.tell();
let received_size = end - start;
if received_size == expected_size {
Ok(result)
} else {
Err(CheckedParseError::Size(SizeError {
expected: expected_size,
received: received_size,
}))
}
}
}
/// Extension trait for factories that ensures fixed size write.
pub trait CheckedSerialize<'a, Ctx: Context<'a>>: Serializable + FixedSizeObject<'a, Ctx> {
/// Verify proper write length using [`Serializer::tell`].
fn serialize_checked(&self, serializer: &mut dyn Serializer) -> Result<(), SizeError> {
let expected_size = self.size();
let start = serializer.tell();
self.serialize(serializer);
let end = serializer.tell();
let received_size = end - start;
if received_size == expected_size {
Ok(())
} else {
Err(SizeError {
expected: expected_size,
received: received_size,
})
}
}
}
impl<'a, Ctx: Context<'a>, F: FixedSizeFactory<'a, Ctx>> CheckedParse<'a, Ctx> for F {}
impl<'a, Ctx: Context<'a>, A: Mentionable<'a, Ctx> + FixedSizeObject<'a, Ctx>>
CheckedSerialize<'a, Ctx> for A
{
}
/// Trait useful for objects which aren't influenced by
/// whether some other type (for example, a generic parameter type)
/// is fixed-size or not.
pub trait AlwaysFixedSize {
fn _size(&self) -> usize;
}
impl<'a, Ctx: Context<'a>, F: AlwaysFixedSize + InlineableFactory<'a, Ctx>>
FixedSizeFactory<'a, Ctx> for F
{
fn size(&self) -> usize {
self._size()
}
}
/// Compile-time analogue of [`AlwaysFixedSize`].
pub trait AlwaysConstSize {
const _SIZE: usize;
}
impl AlwaysFixedSize for F {
fn _size(&self) -> usize {
Self::_SIZE
}
}
impl<'a, Ctx: Context<'a>, F: AlwaysConstSize + InlineableFactory<'a, Ctx>>
ConstSizeFactory<'a, Ctx> for F
{
const SIZE: usize = Self::_SIZE;
}
impl<'a, Ctx: Context<'a>, F: Factory<'a, Ctx>> InlineableFactory<'a, Ctx> for PointFactory {
fn extension_error(&self, tail: &[u8]) -> Self::ParseError {
PointParseError::WrongLength(HASH_SIZE + tail.len())
}
}
impl AlwaysConstSize for PointFactory {
const _SIZE: usize = HASH_SIZE;
}