Using Yoke with a custom cart datatype wrapping a Vec #4908
-
Hi, I am currently writing a protocol stack in Rust. For incoming packets, I built some zerocopy packet parsers based on Fuchsia's packet library, because I liked the ideas described in this presentation: https://www.youtube.com/watch?v=UfMOOxOGCmA The way this works is that you wrap some sequence of bytes in a pub struct Buf<B> {
buf: B,
body: Range<usize>,
} After creating a let v = vec![0x29, 0x03, 0x03, 0x01, 0x01, 0x55, 0xAA, 0x00, 0x17, 0x00, 0x0C, 0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
let mut b = Buf::new(v, ..);
println!("buf before parsing: {:?}", b);
{
let p = b.parse::<CemiPacket<&[u8], CemiLDataInd>>().unwrap();
println!("parsed packet: {:?}", p);
}
println!("buf after parsing: {:?}", b); Which yields this output:
#[derive(Debug, Yokeable)]
pub struct CemiPacket<B: ByteSlice, M: CemiMessage> {
header: LayoutVerified<B, Header>,
additional_info: B,
message: LayoutVerified<B, M>,
npdu: B,
}
#[derive(Copy, Clone, Default, Debug, FromZeroes, FromBytes, AsBytes, Unaligned)]
#[repr(C)]
struct HeaderPrefix {
message_code: u8,
additional_info_len: u8,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, FromZeroes, FromBytes, AsBytes, Unaligned)]
#[repr(C)]
pub struct CemiLDataInd {
ctrl1: Ctrl1Field,
ctrl2: Ctrl2Field,
addr_src: [u8; 2],
addr_dst: [u8; 2],
} The So far, so good. Now I want to pass around the parsed representation and the I tried using let v = vec![0x29, 0x03, 0x03, 0x01, 0x01, 0x55, 0xAA, 0x00, 0x17, 0x00, 0x0C, 0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
let a: Yoke<CemiPacket<&[u8], CemiLDataInd>, Buf<Vec<u8>>> = Yoke::attach_to_cart(Buf::new(v, ..), |mut x| {
x.parse::<CemiPacket<&'static [u8], CemiLDataInd>>().unwrap()
}); At first But now the compiler complains that pub struct MyFakeYoke<C: AsRef<[u8]>> {
yokeable: KindaSortaDangling<CemiPacket<&'static [u8], CemiLDataInd>>,
cart: Buf<C>,
}
fn test_packet_yoke() {
let data = vec![0x29, 0x03, 0x03, 0x01, 0x01, 0x55, 0xAA, 0x00, 0x17, 0x00, 0x0C, 0, 1, 2, 3, 3, 4, 5, 7, 8, 9];
let mut cart = Buf::new(data, ..);
let p = cart.parse::<CemiPacket<&[u8], CemiLDataInd>>().unwrap();
let yokeable = unsafe { <CemiPacket<&[u8], CemiLDataInd> as yoke::Yokeable>::make(p) };
let foo: MyFakeYoke<Vec<u8>> = MyFakeYoke {
cart,
yokeable: KindaSortaDangling::new(yokeable)
};
} This is what rustc complains about:
When trying to do the same with a simple custom struct with just two fn parse<'a, P: ParsablePacket<&'a [u8], ()>>(&'a mut self) -> Result<P, P::Error> I have to admit I think I get the concept on how all of this works and I have read your blog post multiple times to understand what's going on, but I am slightly overwhelmed by all the fine details and I don't know where else to ask. A nudge in the right direction on how I can stuff one of these |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 7 replies
-
The closure you pass to x.parse::<CemiPacket<&'static [u8], CemiLDataInd>>().unwrap() The |
Beta Was this translation helpful? Give feedback.
The signature of
fn parse
is super important. Is it this one you posted?That would not work because you are borrowing
x
as an&mut
, so any additional borrows borrow from the short-lived mutable reference. You can't mutatex
inside ofattach_to_cart
.