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]