[][src]Trait rustbus::wire::unmarshal::traits::Unmarshal

pub trait Unmarshal<'r, 'buf: 'r, 'fds>: Sized + Signature {
    pub fn unmarshal(
        ctx: &mut UnmarshalContext<'fds, 'buf>
    ) -> UnmarshalResult<Self>; }

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::wire::unmarshal::UnmarshalContext;
use rustbus::wire::unmarshal;
use rustbus::signature;
impl Signature for MyStruct {
    fn signature() -> signature::Type {
        signature::Type::Container(signature::Container::Struct(vec![
            u64::signature(),
        ]))
    }

    fn alignment() -> usize {
        8
    }
}  
use rustbus::wire::unmarshal::traits::Unmarshal;
use rustbus::wire::unmarshal::UnmarshalResult;
use rustbus::wire::util;
use rustbus::ByteOrder;
impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, '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.

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, '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
        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 = external_crate::unmarshal_stuff(&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{unmarshalled_stuff}))
    }
}

Required methods

pub fn unmarshal(
    ctx: &mut UnmarshalContext<'fds, 'buf>
) -> UnmarshalResult<Self>
[src]

Loading content...

Implementations on Foreign Types

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for ()[src]

impl<'r, 'buf: 'r, 'fds, E1> Unmarshal<'r, 'buf, 'fds> for (E1,) where
    E1: Unmarshal<'r, 'buf, 'fds> + Sized
[src]

impl<'r, 'buf: 'r, 'fds, E1, E2> Unmarshal<'r, 'buf, 'fds> for (E1, E2) where
    E1: Unmarshal<'r, 'buf, 'fds> + Sized,
    E2: Unmarshal<'r, 'buf, 'fds> + Sized
[src]

impl<'r, 'buf: 'r, 'fds, E1, E2, E3> Unmarshal<'r, 'buf, 'fds> for (E1, E2, E3) where
    E1: Unmarshal<'r, 'buf, 'fds> + Sized,
    E2: Unmarshal<'r, 'buf, 'fds> + Sized,
    E3: Unmarshal<'r, 'buf, 'fds> + Sized
[src]

impl<'r, 'buf: 'r, 'fds, E1, E2, E3, E4> Unmarshal<'r, 'buf, 'fds> for (E1, E2, E3, E4) where
    E1: Unmarshal<'r, 'buf, 'fds> + Sized,
    E2: Unmarshal<'r, 'buf, 'fds> + Sized,
    E3: Unmarshal<'r, 'buf, 'fds> + Sized,
    E4: Unmarshal<'r, 'buf, 'fds> + Sized
[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for u64[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for u32[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for u16[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for i64[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for i32[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for i16[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for u8[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for bool[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for &'r str[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for String[src]

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

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

impl<'r, 'buf: 'r, 'fds, E: Unmarshal<'r, 'buf, 'fds>> Unmarshal<'r, 'buf, 'fds> for Vec<E>[src]

impl<'r, 'buf: 'r, 'fds, K: Unmarshal<'r, 'buf, 'fds> + Hash + Eq, V: Unmarshal<'r, 'buf, 'fds>> Unmarshal<'r, 'buf, 'fds> for HashMap<K, V>[src]

Loading content...

Implementors

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for SignatureWrapper<'r>[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for UnixFd[src]

impl<'r, 'buf: 'r, 'fds> Unmarshal<'r, 'buf, 'fds> for Variant<'fds, 'buf>[src]

impl<'r, 'buf: 'r, 'fds, S: AsRef<str> + Unmarshal<'r, 'buf, 'fds>> Unmarshal<'r, 'buf, 'fds> for ObjectPath<S>[src]

Loading content...