Traits and procedural macros to convert structures and enums to bigendian
data streams.
It's used to send struct
or enum
data to the wire, or receive data from the wire.
The trait is defined as:
// function to convert to network order (bigendian)
pub trait ToNetworkOrder {
// copy structure data to a network-order buffer
fn serialize_to(&self, buffer: &mut Vec<u8>) -> std::io::Result<usize>;
}
// function to convert from network order (big-endian)
pub trait FromNetworkOrder<'a> {
// copy from a network-order buffer to a structure
fn deserialize_from(&mut self, buffer: &mut std::io::Cursor<&'a [u8]>)
-> std::io::Result<()>;
}
It's extensively using the byteorder
crate in order to convert integers or floats
to a bigendian buffer of u8
.
It is compatible with other attributes like those provided by serde
crate.
Just add :
#[derive(FromNetwork)]
to auto-implement theToNetworkOrder
trait#[derive(ToNetwork)]
to auto-implement theFromNetworkOrder
trait#[derive(ToNetwork, FromNetwork)]
to auto-implement theToNetworkOrder
&FromNetworkOrder
traits
The ToNetworkOrder
trait is supported for all structs or enums containing supported primary types (see below for a list of supported types).
The FromNetworkOrder
trait is only supported for C-like unit-only enums or those having a fallback variant.
For the ToNetworkOrder
trait on C-like enums, it needs to be Copy, Clone
.
In addition it's possible to add a field attribute on a struct's field for the FromNetworkOrder
trait:
#[from_network(ignore)]
: the field is not deserialized.#[from_network(debug)]
: adbg!(self.field_name)
statement is inserted after the field is being deserialized.#[from_network(with_fn(func))]
: the functionfunc(&mut self) -> std::io::Result<()>
is called for that field.#[from_network(with_code(block))]
: thecode
block is injected before the field is being deserialized.
Two types of enums are supported for the FromNetworkOrder
trait:
- C-like enums: in that case, the
TryFrom
trait must be defined, and#[from_network(TryFrom)]
must be added as an outer attribute - C-like enums having in addition a catch all fallback value (refer to the
num_enum
crate). In that case, theFrom
trait must be defined and#[from_network(From)]
must be added as an outer attribute
Refer to integration test for examples.
Type | ToNetwork |
FromNetwork |
---|---|---|
all integers & floats |
yes | yes |
char |
yes | yes |
&[u8] |
yes | no |
&str |
yes | no |
String |
yes | no |
Option<T> |
yes | yes |
Vec<T> |
yes | yes |
Box<T> |
yes | yes |
PhantomData<T> |
yes | yes |
() |
yes | yes |
Cell<T> |
yes | yes |
OnceCell<T> |
yes | yes |
RefCell<T> |
yes | yes |
Box<dyn ToNetworkOrder> |
yes | no |
Box<dyn FromNetworkOrder<'a>> |
no | yes |
Ipv4Addr |
yes | yes |
Ipv6Addr |
yes | yes |
Either<L,R> |
yes | no |
Bytes |
yes | no |
BytesMut |
no | yes |
// z field is not deserialized
#[derive(Debug, Default, PartialEq, FromNetwork)]
struct PointAttrNo {
x: u16,
y: u16,
// last field is not deserialized
#[from_network(ignore)]
z: u16,
}
// this function will be called for z field
fn update(p: &mut PointFn) -> std::io::Result<()> {
p.z = 3;
}
#[derive(Debug, Default, PartialEq, FromNetwork)]
struct PointFn {
x: u16,
y: u16,
// last field is not deserialized
#[from_network(with_fn(update))]
z: u16,
}
// the block: self.z = 0xFFFF; is injected
#[derive(Debug, Default, PartialEq, FromNetwork)]
struct PointCode {
x: u16,
y: u16,
// last field is not deserialized
#[from_network(with_code(self.z = 0xFFFF;))]
z: u16,
}
Two examples can be found in the examples
directory:
In general, you should add the #[derive(ToNetwork, FromNetwork)]
derive macros to benefit from the procedural macros which automatically convert structure to network order back and forth. They are included using:
use type2network::{FromNetworkOrder, ToNetworkOrder};
use type2network_derive::{FromNetwork, ToNetwork};
The serde
data model is not managing C-like enums. You have to tap into another crate called serde_repr
.
In addition, using serde, you define a function, not a trait for your struct. As for bincoe, I found it too much
complicated for my needs. Last but not least, it was meant to enhance my understanding of proc macros.
License: MIT OR Apache-2.0