pub trait Unmarshal<'buf, 'fds>: Sized + Signature {
    // Required method
    fn unmarshal(
        ctx: &mut UnmarshalContext<'fds, 'buf>
    ) -> Result<(usize, Self), Error>;
}
Expand description

This trait has to be supported to get parameters ergonomically out of a MarshalledMessage. There are implementations for the base types, Vecs, Hashmaps, and tuples of up to 5 elements if the contained types are Unmarshal. If you deal with basic messages, this should cover all your needs and you dont need to implement this type for your own types.

There is a crate (rustbus_derive) for deriving Unmarshal impls with #[derive(rustbus_derive::Marshal)]. This should work for most of your needs. You can of course derive Signature as well.

If there are special needs, you can implement Unmarshal for your own structs:

Implementing for your own structs

You can of course add your own implementations for types. For this to work properly the signature must be correct and you need to report all bytes you consumed in the T::unmarshal(…) call. THIS INCLUDES PADDING.

Typically your code should look like this:

struct MyStruct{ mycoolint: u64}
use rustbus::wire::marshal::traits::Signature;
use rustbus::signature;
use rustbus::wire::unmarshal;
use rustbus::wire::unmarshal::UnmarshalContext;
use rustbus::wire::unmarshal::traits::Unmarshal;
use rustbus::wire::unmarshal::UnmarshalResult;
use rustbus::wire::marshal::traits::SignatureBuffer;
use rustbus::wire::util;
use rustbus::ByteOrder;

impl Signature for MyStruct {
    fn signature() -> signature::Type {
        signature::Type::Container(signature::Container::Struct(signature::StructTypes::new(vec![
            u64::signature(),
        ]).unwrap()))
    }

    fn alignment() -> usize {
        8
    }
    fn sig_str(s_buf: &mut SignatureBuffer) {
        s_buf.push_static("(ts)");
    }
    fn has_sig(sig: &str) -> bool {
        sig == "(ts)"
    }
}

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for MyStruct {
   fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
        let start_offset = ctx.offset;
        // check that we are aligned properly!
        // This is necessary at the start of each struct! They need to be aligned to 8 bytes!
        let padding = ctx.align_to(Self::alignment())?;

        // decode some stuff and adjust offset
        let (bytes, mycoolint) = u64::unmarshal(ctx)?;
         
        // some more decoding if the struct had more fields
        // ....
         
        //then report the total bytes used by unmarshalling this type (INCLUDING padding at the beginning!):
        let total_bytes = ctx.offset - start_offset;
        Ok((total_bytes, MyStruct{mycoolint}))
    }
}

This is of course just an example, this could be solved by using

let (bytes, mycoolint) =  <(u64,) as Unmarshal>::unmarshal(...)

Cool things you can do

If the message contains some form of secondary marshalling, of another format, you can do this here too, instead of copying the bytes array around before doing the secondary unmarshalling. Just keep in mind that you have to report the accurate number of bytes used, and not to use any bytes in the message, not belonging to that byte array

As an example, lets assume your message contains a byte-array that is actually json data. Then you can use serde_json to unmarshal that array directly here without having to do a separate step for that.

use rustbus::Unmarshal;
use rustbus::wire::unmarshal::UnmarshalResult;
use rustbus::wire::unmarshal::UnmarshalContext;
use rustbus::wire::marshal::traits::Signature;
use rustbus::wire::marshal::traits::SignatureBuffer;
use rustbus::signature;

struct MyStruct{ mycoolint: u64}
impl Signature for MyStruct {
    fn signature() -> signature::Type {
        signature::Type::Container(signature::Container::Struct(signature::StructTypes::new(vec![
            u64::signature(),
        ]).unwrap()))
    }

    fn alignment() -> usize {
        8
    }
    fn sig_str(s_buf: &mut SignatureBuffer) {
        s_buf.push_static("(ts)");
    }
    fn has_sig(sig: &str) -> bool {
        sig == "(ts)"
    }
}

fn unmarshal_stuff_from_raw(raw: &[u8]) -> u64 { 0 }

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for MyStruct {
   fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> UnmarshalResult<Self> {
        let start_offset = ctx.offset;
        // check that we are aligned properly
        let padding = ctx.align_to(Self::alignment())?;

        // get the slice that contains marshalled data, and unmarshal it directly here!
        let (bytes, raw_data) = <&[u8] as Unmarshal>::unmarshal(ctx)?;
        let unmarshalled_stuff = unmarshal_stuff_from_raw(&raw_data);

        //then report the total bytes used by unmarshalling this type (INCLUDING padding at the beginning!):
        let total_bytes = ctx.offset - start_offset;
        Ok((total_bytes, MyStruct{mycoolint: unmarshalled_stuff}))
    }
}

Required Methods§

source

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, Self), Error>

Implementations on Foreign Types§

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u64

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, u64), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i64

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, i64), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u16

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, u16), Error>

source§

impl<'buf, 'fds, E> Unmarshal<'buf, 'fds> for Vec<E, Global>where E: Unmarshal<'buf, 'fds>,

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, Vec<E, Global>), Error>

source§

impl<'buf, 'fds, K, V> Unmarshal<'buf, 'fds> for HashMap<K, V, RandomState>where K: Unmarshal<'buf, 'fds> + Hash + Eq, V: Unmarshal<'buf, 'fds>,

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, HashMap<K, V, RandomState>), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u32

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, u32), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf str

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, &'buf str), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for String

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, String), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i16

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, i16), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u8

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, u8), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i32

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, i32), Error>

source§

impl<'buf, 'fds, E1, E2, E3> Unmarshal<'buf, 'fds> for (E1, E2, E3)where E1: Unmarshal<'buf, 'fds>, E2: Unmarshal<'buf, 'fds>, E3: Unmarshal<'buf, 'fds>,

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, (E1, E2, E3)), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf [u8]

for byte arrays we can give an efficient method of decoding. This will bind the returned slice to the lifetime of the buffer.

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, &'buf [u8]), Error>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for bool

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, bool), Error>

source§

impl<'buf, 'fds, E> Unmarshal<'buf, 'fds> for Cow<'buf, [E]>where E: Unmarshal<'buf, 'fds> + Clone,

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, Cow<'buf, [E]>), Error>

source§

impl<'buf, 'fds, E1> Unmarshal<'buf, 'fds> for (E1,)where E1: Unmarshal<'buf, 'fds>,

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, (E1,)), Error>

source§

impl<'buf, 'fds, E1, E2, E3, E4> Unmarshal<'buf, 'fds> for (E1, E2, E3, E4)where E1: Unmarshal<'buf, 'fds>, E2: Unmarshal<'buf, 'fds>, E3: Unmarshal<'buf, 'fds>, E4: Unmarshal<'buf, 'fds>,

source§

impl<'buf, 'fds, E1, E2> Unmarshal<'buf, 'fds> for (E1, E2)where E1: Unmarshal<'buf, 'fds>, E2: Unmarshal<'buf, 'fds>,

source§

fn unmarshal( ctx: &mut UnmarshalContext<'fds, 'buf> ) -> Result<(usize, (E1, E2)), Error>

Implementors§

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf async_rustbus::rustbus_core::path::ObjectPath

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for HdrVar<'fds, 'buf>

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for DynamicHeader

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for ObjectPathBuf

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for UnixFd

source§

impl<'buf, 'fds> Unmarshal<'buf, 'fds> for Variant<'fds, 'buf>

source§

impl<'buf, 'fds, S> Unmarshal<'buf, 'fds> for async_rustbus::rustbus_core::wire::ObjectPath<S>where S: AsRef<str> + Unmarshal<'buf, 'fds>,

source§

impl<'buf, 'fds, S> Unmarshal<'buf, 'fds> for SignatureWrapper<S>where S: AsRef<str> + From<&'buf str> + Unmarshal<'buf, 'fds>,