cetra3/tmq

How do I get a multipart message as a &[u8]? Examples don't include it.

Closed this issue · 2 comments

Jaxkr commented

Desired outcome: I want to pass a byte array to my function deserialize which takes a single &[u8] argument.

Currently, I do the following as a temporary measure because most messages are not multipart.

let msg: Multipart = msg?;
let data = msg.into_iter().next().unwrap();
let message_result = deserialize(&data);

I would like to get all members of the multipart message and combine them into a single byte array.

I tried copying the pull.rs example and modifying it to read:

msg.iter()
    .map(|item| item.as_slice())
    .collect::<Vec<&u8>>();

but I got the compiler error

error[E0658]: use of unstable library feature 'slice_pattern': stopgap trait for slice patterns
 --> src/transport/zeromq_incoming.rs:1:5
  |
1 | use core::slice::SlicePattern;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #56345 <https://github.com/rust-lang/rust/issues/56345> for more information

I've tried a couple other things and also noticed that the Deref impl for Message seems to return a reference to the underlying message byte array, but I couldn't figure out how to use it without running into a "doesn't have a size known at compile-time" error.

I've been banging my head against a wall for what feels like hours trying to figure this out, would massively appreciate your help. Thanks for this great library.

It seems that by modifying the example code, your IDE has auto-imported some part of stdlib that is currently unstable. You should remove that import from zeromq_incoming.rs:1. You probably tried to use as_slice, but that's not available on zmq::Message, to get a byte slice out of it, you need to use deref() (see below).

Each ZMQ multi-part message consists of several messages. You can get a byte slice (&[u8]) from each message easily using the Deref impl (by calling deref() on it). However, the slices of the individual messages are independent, so you cannot get a single [u8] slice out of them directly, because a slice has to be contiguous in memory.

If you want such a contiguous slice, the easiest solution is to go through the messages, collect them to a single Vec of bytes and then send that to your deserialize function:

let mut data = Vec::new();
for message in msg {
    data.extend_from_slice(message.deref());
}
let slice: &[u8] = data.as_slice();
deserialize(slice);
Jaxkr commented

Thank you. <3