capnproto / capnproto-rust

Cap'n Proto for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to read unknown number of messages

quartox opened this issue · comments

I am trying to use try_read_message on a vector that contains an unknown number of messages. I could not figure out how to do this without copying the private function read_segment_table. If I convert the Reader<OwnedSegments> into OwnedSegments then the Reader is lost. Is there a more sensible way to do this?

fn readers_from_data(data: Vec<u8>)  -> Vec<capnp::message::Reader<OwnedSegments>> {
    let reader_options = ::capnp::message::ReaderOptions::new();
    let mut offset = 0;
    let mut readers = vec![];
    loop {
        let attempt = read_segment_table(&mut &data[offset..], reader_options).unwrap();
        match attempt {
            Some(segment_table) => {
                let end_of_message = 8*(segment_table.total_words() + 1);
                let Some(reader) = serialize::try_read_message(&data[offset..offset+end_of_message], reader_options).unwrap() else {return readers};
                readers.push(reader);
                offset += end_of_message;
            }
            None => break,
        }
    }
    readers
}

One way to read multiple messages from data is to wrap the data in a Cursor.
Another way is to pass a &mut &[u8] to try_read_message(). The value of that mutable reference after the call will point to the rest of the byte stream.

Thanks! That simplified it significantly.

pub fn readers_from_data(data: Vec<u8>) -> Vec<capnp::message::Reader<serialize::OwnedSegments>> {
    let reader_options = ::capnp::message::ReaderOptions::new();
    let mut readers = vec![];
    let mut current_message = &mut &data[..];
    loop {
        let Some(reader) =
            serialize::try_read_message(&mut current_message, reader_options).unwrap()
        else {
            break;
        };
        readers.push(reader)
    }
    readers
}