I am trying to create a generic serialization scheme for structs. Following an answer given on a similar thread, I have the following setup:
#[repr(packed)]
struct MyStruct {
bytes: [u8; 4]
}
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
::std::slice::from_raw_parts(
(p as *const T) as *const u8,
::std::mem::size_of::<T>(),
)
}
fn main() {
let s = MyStruct { bytes: [0u8, 1u8, 2u8, 3u8].to_owned() };
let bytes: &[u8] = unsafe { any_as_u8_slice(&s) };
println!("{:?}", bytes);
}
Output:
[0, 1, 2, 3]
This works great, however it does not take into account struct members that are dynamically sized like Vec<u8> and their size needs to determined at runtime. Ideally, I would like to encode each element in the Vec<u8> as bytes and add a prefix for indicating how many bytes to read.
At the moment I have this:
#[repr(packed)]
struct MyStruct {
bytes: Vec<u8>
}
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
::std::slice::from_raw_parts(
(p as *const T) as *const u8,
::std::mem::size_of::<T>(),
)
}
fn main() {
let s = MyStruct { bytes: [0u8, 1u8, 2u8, 3u8].to_vec() };
let bytes: &[u8] = unsafe { any_as_u8_slice(&s) };
println!("{:?}", bytes);
}
Output:
[208, 25, 156, 239, 136, 85, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]
I assume the output above is referencing a pointer of sorts, but I am not sure.
Currently, the bincode crate does this together with the serde crate, but it serializes the length of the vector as usize. I would rather want to specify this and encode the length as u8, as explained in this thread. Unfortunately, the best solution here is to rewrite the Bincode library, which made me look for any alternative solution.
EDIT
Implementation using serde and bincode:
use serde::{Serialize};
#[derive(Clone, Debug, Serialize)]
struct MyStruct {
bytes: Vec<u8>
}
fn main() {
let s = MyStruct { bytes: [0u8, 1u8, 2u8, 3u8].to_vec() };
let bytes = bincode::serialize(&s).unwrap();
println!("{:?}", bytes);
}
Output:
[4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]
Wanted output:
[4, 0, 1, 2, 3]