So I did a pull request to the hex
crate:
https://github.com/KokaKiwi/rust-hex/pull/83
This sort of scenario is not too uncommon in data flows especially when you want to squeeze everything bit out. E.g. for something like #ZMODEM you’d prefer the implementation to scale from microcontroller to Intel Xeon.
Usage example in my crate:
if encoding == Encoding::ZHEX {
hex::decode_in_slice(&mut out).or::<io::Error>(Err(ErrorKind::InvalidData.into()))?;
out.truncate(out.len() / 2);
}
One thing that I had to dig up from previous #Enarx work was core::marker::PhantomData
. It is not so well known but pretty important concept inside Rust.
PhantomData
is a zero-sized struct that merely acts as a life-time indicator for the other parameter, which are usually pointers on where it is applied. It is used to implement many of the core structs such as Rc
to name one instance.
It is pretty good lesson on how lifetime parameters interact with the Rust compiler.
I’d even say that if you understand PhantomData
, then you have the basic understanding of Rust, and if not, you still have to learn a bit. It is the block that the whole core library is based on after all.
I’d actually recommend to do few exercises with just from_raw_parts
and lifetime parameters before using zerocopy
because that sort of gives you full tutorial on what that particular crate does internally :-) I sort of enjoy thinking of those scenarios so it also takes some fun away :-)
All the crates that #Google has done for #Rust seem to be like stuff I’ve been looking for to get better control of the memory.
Especially zerocopy
is a time saver as it has all the thinkable stuff that I have used previously core::slice::from_raw_parts
and spent a lot of time thinking of all the possible safety scenarios, such as this recent one:
impl<'a> From<&'a Header> for &'a [u8] {
fn from(value: &Header) -> Self {
// SAFETY: out-of-boundary is not possible, given that the size constraint
// exists in the struct definition. The lifetime parameter links the lifetime
// of the header reference to the slice.
unsafe { from_raw_parts((value as *const Header) as *const u8, size_of::<Header>()) }
}
}
Previously I’ve had to do similar consideration in the #Enarx project. You can do these by hand but it is nice to have a common crate, which is tested by many for these risky scenarios.
Other mentionable crate from Google is tinyvec
, which I’m going to use in zmodem2
to remove internal heap usage.