[][src]Struct rubble::bytes::BytesOr

pub struct BytesOr<'a, T: ?Sized>(_);

Reference to a T, or to a byte slice that can be decoded as a T.

Motivation

Many packets can contain dynamically-sized lists of objects. These packets all need to implement ToBytes and FromBytes. For FromBytes, it is impossible to go from &[u8] to &[T].

A workaround is to just store the &[u8] and decode Ts only when necessary. However, this isn't very type-safe and also makes it difficult to create the type when you have a list of Ts, but can't easily get a &[u8] (such as when creating a packet to be sent out). You'd have to define your own byte buffer and serialize the Ts into it, which is problematic due to the potentially unknown size requirement and lifetime management.

A workaround around the workaround would be to use 2 types for the same packet: One storing a &[u8] and implementing FromBytes which can only do deserialization, and one storing a &[T] and implementing ToBytes, which can only do serialization. This has the obvious drawback of essentially duplicating all packet definitions.

Rubble's solution for this is BytesOr: It can store either an &[u8] or a &T (where T might be a slice), and always implements ToBytes and FromBytes if T does. Methods allowing access to the stored T (or the elements in the &[T] slice) will either directly return the value, or decode it using its FromBytes implementation.

When encoding a T, BytesOr::from_ref can be used to store a &T in a BytesOr, which can then be turned into bytes via ToBytes. When decoding data, FromBytes can be used to create a BytesOr from bytes.

This type can also be used in structures when storing a T directly is not desirable due to size concerns: It could be inside a rarely-encountered variant or would blow up the total size of the containing enum). The size of BytesOr is currently 2 usizes plus a discriminant byte, but could potentially be (unsafely) reduced further, should that be required.

Methods

impl<'a, T: ?Sized> BytesOr<'a, T>[src]

pub fn from_ref(value: &'a T) -> Self[src]

Creates a BytesOr that holds on to a T via reference.

For creating a BytesOr that references a byte slice, the FromBytes impl(s) can be used.

impl<'a, T: Copy + FromBytes<'a>> BytesOr<'a, T>[src]

pub fn read(&self) -> T[src]

Reads the T, possibly by parsing the stored bytes.

If self already stores a reference to a T, the T will just be copied out. If self stores a byte slice, the T will be parsed using its FromBytes implementation.

impl<'a, T: Copy + FromBytes<'a>> BytesOr<'a, T>[src]

pub fn iter(&self) -> impl Iterator<Item = T> + 'a[src]

Returns an iterator over all Ts stored in self (which is just one T in this case).

This method exists to mirror its twin implemented for BytesOr<'a, [T]>.

impl<'a, T: Copy + FromBytes<'a>> BytesOr<'a, [T]>[src]

pub fn iter(&self) -> impl Iterator<Item = T> + 'a[src]

Returns an iterator over all Ts stored in self.

The iterator will copy or decode Ts out of self.

Trait Implementations

impl<'a, T: ToBytes + ?Sized> ToBytes for BytesOr<'a, T>[src]

impl<'a, T: FromBytes<'a>> FromBytes<'a> for BytesOr<'a, T>[src]

Creates a BytesOr that stores bytes that can be decoded to a T.

This will check that bytes can indeed be decoded as a T using its FromBytes implementation, and returns an error if not.

The ByteReader will be advanced to point past the decoded T if the conversion succeeds.

impl<'a, T: FromBytes<'a>> FromBytes<'a> for BytesOr<'a, [T]>[src]

Creates a BytesOr that stores bytes that can be decoded to a sequence of Ts.

This will check that bytes can indeed be decoded as a sequence of Ts, and returns an error if not. Note that this will read as many Ts as possible until the ByteReader is at its end of input. Any trailing data after the list of Ts will result in an error.

The ByteReader will be advanced to point past the decoded list of Ts if the conversion succeeds. In that case, it will be at EOF and no more data can be read.

impl<'a, T: ?Sized> Copy for BytesOr<'a, T>[src]

impl<'a, T: Debug + FromBytes<'a> + Copy> Debug for BytesOr<'a, T>[src]

impl<'a, T: Debug + FromBytes<'a> + Copy> Debug for BytesOr<'a, [T]>[src]

impl<'a, T: ?Sized> From<&'a T> for BytesOr<'a, T>[src]

impl<'a, T: ?Sized> Clone for BytesOr<'a, T>[src]

fn clone_from(&mut self, source: &Self)
1.0.0
[src]

Performs copy-assignment from source. Read more

Auto Trait Implementations

impl<'a, T: ?Sized> Send for BytesOr<'a, T> where
    T: Sync

impl<'a, T: ?Sized> Sync for BytesOr<'a, T> where
    T: Sync

Blanket Implementations

impl<T, U> TryFrom for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T> From for T[src]

impl<T, U> TryInto for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T, U> Into for T where
    U: From<T>, 
[src]

impl<T> Borrow for T where
    T: ?Sized
[src]

impl<T> BorrowMut for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]