[−][src]Struct rubble::bytes::BytesOr
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.
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 T
s 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 T
s stored in self
.
The iterator will copy or decode T
s out of self
.
Trait Implementations
impl<'a, T: ToBytes + ?Sized> ToBytes for BytesOr<'a, T>
[src]
fn to_bytes(&self, buffer: &mut ByteWriter) -> Result<(), Error>
[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.
fn from_bytes(bytes: &mut ByteReader<'a>) -> Result<Self, Error>
[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 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.
fn from_bytes(bytes: &mut ByteReader<'a>) -> Result<Self, Error>
[src]
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(&self) -> Self
[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,
T: Sync,
impl<'a, T: ?Sized> Sync for BytesOr<'a, T> where
T: Sync,
T: Sync,
Blanket Implementations
impl<T, U> TryFrom for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T> From for T
[src]
impl<T, U> TryInto for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T, U> Into for T where
U: From<T>,
[src]
U: From<T>,
impl<T> Borrow for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,