Struct rubble::bytes::BytesOr [−][src]
Expand description
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 T
s 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
T
s, 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 T
s 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 usize
s plus a discriminant byte,
but could potentially be (unsafely) reduced further, should that be required.
Tuple Fields
0: Inner<'a, T>
Implementations
Trait Implementations
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.
Decode a Self
from a byte slice, advancing bytes
to point past the data that was read. Read more
Creates a BytesOr
that stores bytes that can be decoded to a sequence of T
s.
This will check that bytes
can indeed be decoded as a sequence of T
s, and returns an error
if not. Note that this will read as many T
s as possible until the ByteReader
is at its
end of input. Any trailing data after the list of T
s will result in an error.
The ByteReader
will be advanced to point past the decoded list of T
s if the conversion
succeeds. In that case, it will be at EOF and no more data can be read.
Decode a Self
from a byte slice, advancing bytes
to point past the data that was read. Read more
Auto Trait Implementations
impl<'a, T: ?Sized> RefUnwindSafe for BytesOr<'a, T> where
T: RefUnwindSafe,
impl<'a, T: ?Sized> UnwindSafe for BytesOr<'a, T> where
T: RefUnwindSafe,
Blanket Implementations
Mutably borrows from an owned value. Read more