use crate::machine::DxMachineError;
use serde::{Deserialize, Serialize};
pub fn to_bytes<T: Serialize>(value: &T) -> Result<Vec<u8>, DxMachineError> {
let payload = bincode::serialize(value)
.map_err(|e| DxMachineError::InvalidData(format!("Serialization failed: {}", e)))?;
let total_size = 16 + payload.len();
let mut buffer = Vec::with_capacity(total_size);
buffer.extend_from_slice(&[
0x5A, 0x44, 0x01, 0x01, ]);
buffer.extend_from_slice(&(payload.len() as u32).to_le_bytes());
buffer.extend_from_slice(&[0u8; 8]);
buffer.extend_from_slice(&payload);
Ok(buffer)
}
pub fn from_bytes<'a, T: Deserialize<'a>>(bytes: &'a [u8]) -> Result<T, DxMachineError> {
if bytes.len() < 16 {
return Err(DxMachineError::BufferTooSmall {
required: 16,
actual: bytes.len(),
});
}
if bytes[0] != 0x5A || bytes[1] != 0x44 {
return Err(DxMachineError::InvalidMagic);
}
let payload_len = u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]) as usize;
let required = 16 + payload_len;
if bytes.len() < required {
return Err(DxMachineError::BufferTooSmall {
required,
actual: bytes.len(),
});
}
let payload_bytes = &bytes[16..required];
bincode::deserialize(payload_bytes)
.map_err(|e| DxMachineError::InvalidData(format!("Deserialization failed: {}", e)))
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
struct TestStruct {
id: u64,
name: String,
active: bool,
}
#[test]
fn test_roundtrip() {
let original = TestStruct {
id: 42,
name: "test".to_string(),
active: true,
};
let bytes = to_bytes(&original).unwrap();
assert_eq!(bytes[0], 0x5A);
assert_eq!(bytes[1], 0x44);
let decoded: TestStruct = from_bytes(&bytes).unwrap();
assert_eq!(original, decoded);
}
#[test]
fn test_vec_roundtrip() {
let original = vec![1, 2, 3, 4, 5];
let bytes = to_bytes(&original).unwrap();
let decoded: Vec<i32> = from_bytes(&bytes).unwrap();
assert_eq!(original, decoded);
}
}