|
@@ -1,6 +1,6 @@
|
|
|
use std::{error::Error, fmt::Debug};
|
|
use std::{error::Error, fmt::Debug};
|
|
|
|
|
|
|
|
-use crate::hash;
|
|
|
|
|
|
|
+use crate::{binary::checksum, hash};
|
|
|
|
|
|
|
|
pub type Result<T> = std::result::Result<T, DeserializationError>;
|
|
pub type Result<T> = std::result::Result<T, DeserializationError>;
|
|
|
|
|
|
|
@@ -8,6 +8,8 @@ pub type Result<T> = std::result::Result<T, DeserializationError>;
|
|
|
pub enum DeserializationError {
|
|
pub enum DeserializationError {
|
|
|
InvalidSignature,
|
|
InvalidSignature,
|
|
|
InvalidSignatureLength,
|
|
InvalidSignatureLength,
|
|
|
|
|
+ InvalidChecksum,
|
|
|
|
|
+ InvalidChecksumLength,
|
|
|
InvalidDataLength,
|
|
InvalidDataLength,
|
|
|
#[allow(dead_code)]
|
|
#[allow(dead_code)]
|
|
|
InvalidData(&'static str),
|
|
InvalidData(&'static str),
|
|
@@ -24,6 +26,7 @@ impl std::fmt::Display for DeserializationError {
|
|
|
|
|
|
|
|
pub trait Serialize {
|
|
pub trait Serialize {
|
|
|
const SIGNATURE: &'static str;
|
|
const SIGNATURE: &'static str;
|
|
|
|
|
+ const CHECKSUM_LENGTH: usize = 1;
|
|
|
const LENGTH: usize = 0;
|
|
const LENGTH: usize = 0;
|
|
|
|
|
|
|
|
fn signature() -> [u8; 8] {
|
|
fn signature() -> [u8; 8] {
|
|
@@ -37,8 +40,15 @@ pub trait Serialize {
|
|
|
Self: Sized;
|
|
Self: Sized;
|
|
|
|
|
|
|
|
fn serialize_checked(&self) -> Vec<u8> {
|
|
fn serialize_checked(&self) -> Vec<u8> {
|
|
|
- let mut serialized = Self::signature().to_vec();
|
|
|
|
|
- serialized.extend_from_slice(&self.serialize_unchecked());
|
|
|
|
|
|
|
+ let mut serialized = Vec::new();
|
|
|
|
|
+ let inner = self.serialize_unchecked();
|
|
|
|
|
+
|
|
|
|
|
+ let checksum = checksum(&inner);
|
|
|
|
|
+
|
|
|
|
|
+ serialized.extend_from_slice(&Self::signature());
|
|
|
|
|
+ serialized.extend_from_slice(&[checksum]);
|
|
|
|
|
+ serialized.extend_from_slice(&inner);
|
|
|
|
|
+
|
|
|
serialized
|
|
serialized
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -54,17 +64,27 @@ pub trait Serialize {
|
|
|
return Err(DeserializationError::InvalidSignatureLength);
|
|
return Err(DeserializationError::InvalidSignatureLength);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if data.len() < signature.len() + Self::CHECKSUM_LENGTH {
|
|
|
|
|
+ return Err(DeserializationError::InvalidChecksumLength);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
let encoded_sig = &data[..signature.len()];
|
|
let encoded_sig = &data[..signature.len()];
|
|
|
if encoded_sig != signature {
|
|
if encoded_sig != signature {
|
|
|
return Err(DeserializationError::InvalidSignature);
|
|
return Err(DeserializationError::InvalidSignature);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let post_signature_data = &data[signature.len()..];
|
|
|
|
|
- if Self::LENGTH > 0 && post_signature_data.len() != Self::LENGTH as usize {
|
|
|
|
|
|
|
+ let expected_checksum = data[signature.len()];
|
|
|
|
|
+
|
|
|
|
|
+ let inner_data = &data[signature.len() + Self::CHECKSUM_LENGTH..];
|
|
|
|
|
+ if Self::LENGTH > 0 && inner_data.len() != Self::LENGTH as usize {
|
|
|
return Err(DeserializationError::InvalidDataLength);
|
|
return Err(DeserializationError::InvalidDataLength);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Self::deserialize_unchecked(post_signature_data)
|
|
|
|
|
|
|
+ if checksum(&inner_data) != expected_checksum {
|
|
|
|
|
+ return Err(DeserializationError::InvalidChecksum);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Self::deserialize_unchecked(inner_data)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|