macro_rules! with_order { ( ($($src: expr ),*), $endianness: expr, |$($bo: ident ),*| $e: expr ) => { ... } ($src: expr, $endianness: expr, |$bo: ident| $e: expr ) => { ... } }
Creates a scope for reading or writing with run-time byte order awareness.
The condition of whether to read or write data in big endian or little
endian is sure to be triggered only once, at the beginning of the scope.
The given expression $e
is then monomorphized for both cases.
Pass something that implements Read
or Write
, and something which
evaluates to a byte order descriptor (typically Endianness
).
What follows is a pseudo-closure declaration exposing the same value
with the expected byte order awareness.
#[macro_use] extern crate byteordered;
use byteordered::Endianness;
let e: Endianness = get_endianness();
let mut sink = Vec::new();
with_order!(&mut sink, e, |dest| {
// dset is a `ByteOrdered<_, StaticEndianness<_>>`
dest.write_u32(8)?;
dest.write_u32(1024)?;
dest.write_u32(0xF0FF_F0FF)?;
});
assert_eq!(sink.len(), 12);
Moreover, you can pass multiple readers or writers to be augmented with the same implicit byte order. Note that the macro requires a literal tuple expression.
#[macro_use] extern crate byteordered;
use byteordered::Endianness;
let e: Endianness = get_endianness();
let (mut sink1, mut sink2) = (Vec::new(), Vec::new());
with_order!((&mut sink1, &mut sink2), e, |dest1, dest2| {
dest1.write_u32(0x0000_EEFF)?;
dest2.write_u32(0xFFEE_0000)?;
});
assert_eq!(&sink1, &[0xFF, 0xEE, 0x00, 0x00]);
assert_eq!(&sink2, &[0x00, 0x00, 0xEE, 0xFF]);
One might think that this improves performance, since a runtime-bound
ByteOrdered
with a sequence of reads/writes would expand into one check
for each method call:
use byteordered::{ByteOrdered, Endianness};
let mut dst = ByteOrdered::runtime(Vec::new(), get_endianness());
// dynamic dispatch each time (or is it?)
dst.write_u32(8)?;
dst.write_u32(1024)?;
dst.write_u32(0xF0FF_F0FF)?;
However, because the compiler is known to optimize these checks away in the same context, making a scope for that purpose is not always necessary. On the other hand, this can be seen as yet another way to create and manage data sources/destinations with byte order awareness.