Browse Source

Serialize checksum

Rain 9 tháng trước cách đây
mục cha
commit
5eb8010a83
2 tập tin đã thay đổi với 35 bổ sung6 xóa
  1. 9 0
      utils/src/binary.rs
  2. 26 6
      utils/src/serialize.rs

+ 9 - 0
utils/src/binary.rs

@@ -63,3 +63,12 @@ mod test {
         assert_eq!(fuzzy.len(), data.len());
     }
 }
+
+pub fn checksum(data: &[u8]) -> u8 {
+    let mut checksum: u8 = 0;
+    for byte in data {
+        checksum = checksum.wrapping_add(*byte);
+    }
+
+    checksum
+}

+ 26 - 6
utils/src/serialize.rs

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