Bladeren bron

communicator: add Serializable for pairs

Lennart Braun 2 jaren geleden
bovenliggende
commit
6876143656
1 gewijzigde bestanden met toevoegingen van 79 en 0 verwijderingen
  1. 79 0
      communicator/src/traits.rs

+ 79 - 0
communicator/src/traits.rs

@@ -62,12 +62,15 @@ impl<T: Serializable + Default, const N: usize> Serializable for [T; N] {
     fn bytes_required() -> usize {
         T::bytes_required() * N
     }
+
     fn to_bytes(&self) -> Vec<u8> {
         slice_to_bytes(self.as_slice())
     }
+
     fn into_bytes(&self, buf: &mut [u8]) -> Result<(), Error> {
         slice_into_bytes(self.as_slice(), buf)
     }
+
     fn from_bytes(buf: &[u8]) -> Result<Self, Error> {
         if buf.len() != Self::bytes_required() {
             return Err(Error::DeserializationError(
@@ -81,6 +84,47 @@ impl<T: Serializable + Default, const N: usize> Serializable for [T; N] {
     }
 }
 
+impl<T: Serializable, U: Serializable> Serializable for (T, U) {
+    fn bytes_required() -> usize {
+        T::bytes_required() + U::bytes_required()
+    }
+
+    fn to_bytes(&self) -> Vec<u8> {
+        let num_t_bytes = T::bytes_required();
+        let num_u_bytes = U::bytes_required();
+        let mut buf = vec![0u8; num_t_bytes + num_u_bytes];
+        self.0.into_bytes(&mut buf[..num_t_bytes]).unwrap();
+        self.1.into_bytes(&mut buf[num_t_bytes..]).unwrap();
+        buf
+    }
+
+    fn into_bytes(&self, buf: &mut [u8]) -> Result<(), Error> {
+        let num_t_bytes = T::bytes_required();
+        let num_u_bytes = U::bytes_required();
+        if buf.len() != num_t_bytes + num_u_bytes {
+            return Err(Error::SerializationError(
+                "supplied buffer has unexpected size".to_owned(),
+            ));
+        }
+        self.0.into_bytes(&mut buf[..num_t_bytes]).unwrap();
+        self.1.into_bytes(&mut buf[num_t_bytes..]).unwrap();
+        Ok(())
+    }
+
+    fn from_bytes(buf: &[u8]) -> Result<Self, Error> {
+        let num_t_bytes = T::bytes_required();
+        let num_u_bytes = U::bytes_required();
+        if buf.len() != num_t_bytes + num_u_bytes {
+            return Err(Error::DeserializationError(
+                "supplied buffer has unexpected size".to_owned(),
+            ));
+        }
+        let t = T::from_bytes(&buf[..num_t_bytes])?;
+        let u = U::from_bytes(&buf[num_t_bytes..])?;
+        Ok((t, u))
+    }
+}
+
 macro_rules! impl_serializable_for_uints {
     ($type:ty) => {
         impl Serializable for $type {
@@ -179,9 +223,44 @@ mod tests {
             }
         };
     }
+
     make_test_serialiable_for_uint_arrays!(test_serialize_u8_array, u8, 42);
     make_test_serialiable_for_uint_arrays!(test_serialize_u16_array, u16, 42);
     make_test_serialiable_for_uint_arrays!(test_serialize_u32_array, u32, 42);
     make_test_serialiable_for_uint_arrays!(test_serialize_u64_array, u64, 42);
     make_test_serialiable_for_uint_arrays!(test_serialize_u128_array, u128, 42);
+
+    macro_rules! make_test_serialiable_for_pairs {
+        ($test_name:ident, $type_t:ty, $type_u:ty) => {
+            #[test]
+            fn $test_name() {
+                type T = $type_t;
+                type U = $type_u;
+                type P = (T, U);
+                assert_eq!(
+                    P::bytes_required(),
+                    T::bytes_required() + U::bytes_required()
+                );
+                for _ in 0..100 {
+                    let val: P = thread_rng().gen();
+                    let serialized = val.to_bytes();
+                    let mut serialized2 = vec![0u8; P::bytes_required()];
+                    val.into_bytes(&mut serialized2).unwrap();
+                    assert_eq!(serialized.len(), P::bytes_required());
+                    let new_val = <P>::from_bytes(&val.to_bytes());
+                    assert!(new_val.is_ok());
+                    assert_eq!(new_val.unwrap(), val);
+                }
+            }
+        };
+    }
+
+    make_test_serialiable_for_pairs!(test_serialize_pair_u8_u32, u8, u32);
+    make_test_serialiable_for_pairs!(test_serialize_pair_u8array_u32, [u8; 13], u32);
+    make_test_serialiable_for_pairs!(test_serialize_pair_u128array_u16array, u128, [u16; 7]);
+    make_test_serialiable_for_pairs!(
+        test_serialize_pair_nested_uints,
+        u8,
+        (u16, (u32, (u64, u128)))
+    );
 }