Expand description
Simple packet-based protocol definitions in Rust.
- The Parcel trait defines any type that can be serialized to a connection.
- The wire module deals with transmission of Parcel objects.
§Examples
§Get the raw bytes representing a parcel.
extern crate protocol;
#[macro_use] extern crate protocol_derive;
#[derive(Protocol, Debug, PartialEq)]
pub struct Health(pub u8);
#[derive(Protocol, Debug, PartialEq)]
pub struct Player {
pub name: String,
pub health: Health,
pub position: (i16, i16, i16),
pub velocity: (i16, i16, i16),
}
use protocol::Parcel;
assert_eq!(vec![
0, 0, 0, 3, // "Bob" string length prefix
b'B', b'o', b'b', // The string "Bob".
100, // The health byte.
0, 10, 0, 81, 255, 151, // 2-byte x-position, y-position, and z-position.
0, 0, 0, 0, 0, 0, // 2-byte x-velocity, y-velocity, and z-velocity.
], Player {
name: "Bob".to_owned(),
health: Health(100),
position: (10, 81, -105),
velocity: (0, 0, 0),
}.raw_bytes(&protocol::Settings::default()).unwrap());
§Enums
Every enum has a value for each variant used to distinguish between each variant. This can be as simple as a 32-bit integer representing the variant’s index. This is called the discriminator.
§String discriminators
extern crate protocol;
#[macro_use] extern crate protocol_derive;
// This enum, like all enums, defaults to using String discriminators.
#[derive(Protocol, Debug, PartialEq)]
enum Foo { A, B, C }
// This enum explicitly specifies a string discriminant.
//
// This is the default anyway and thus it is identical in layout
// to the previous enum.
#[derive(Protocol, Debug, PartialEq)]
#[protocol(discriminant = "string")]
enum Bar { A, B, C }
By default, enums have String
discriminators. This means that
when serializing enum values to and from bytes, unless otherwise
specified the variant’s full name will be transmitted as a string.
This allows variants to be added, modified, or reordered in a backwards-compatible way.
§Integer discriminators
extern crate protocol;
#[macro_use] extern crate protocol_derive;
// An enum with integer discriminators.
#[derive(Protocol, Debug, PartialEq)]
#[protocol(discriminant = "integer")]
enum Baz {
Fizz = 0, // override the default first discriminator of 1
Buzz, // defaults to `prior discriminator + 1`, therefore has a discriminator of 1.
Bing, // defaults to `prior discriminator + 1`, therefore has a discriminator of 2.
Boo = 1234,
Beez, // defaults to `prior discriminator + 1`, therefore has a discriminator of 1235.
}
use protocol::{Enum, Parcel};
// By default, integer discriminators are 32-bits.
assert_eq!([0u8, 0, 0, 2], &Baz::Bing.discriminator().raw_bytes(&protocol::Settings::default()).unwrap()[..]);
assert_eq!(0, Baz::Fizz.discriminator());
assert_eq!(1, Baz::Buzz.discriminator());
assert_eq!(2, Baz::Bing.discriminator());
assert_eq!(1234, Baz::Boo.discriminator());
assert_eq!(1235, Baz::Beez.discriminator());
It is possible to set the underlying integer type via the #[repr(<type>)]
attribute.
extern crate protocol;
#[macro_use] extern crate protocol_derive;
#[derive(Protocol, Debug, PartialEq)]
#[protocol(discriminant = "integer")]
#[repr(u8)] // Force discriminators to be 8-bit.
pub enum Hello {
World(String), SolarSystem(String), LocalGroup(String),
Universe(String), Everything(String),
}
use protocol::{Enum, Parcel};
assert_eq!([2, // 1-byte discriminator
0, 0, 0, 3, // string length
b'f', b'o', b'o', // the string
], &Hello::SolarSystem("foo".to_owned()).raw_bytes(&protocol::Settings::default()).unwrap()[..]);
Discriminators can be overriden on a per-variant basis via
the #[protocol(discriminator(<value>))]
attribute.
In the case of trivial enums with no fields,
the Variant = <discriminator>
syntax may be used.
extern crate protocol;
#[macro_use] extern crate protocol_derive;
#[derive(Protocol, Debug, PartialEq)]
#[protocol(discriminant = "integer")]
#[repr(u8)] // Force discriminators to be 8-bit.
enum Numbered {
A = 1, B = 2, C = 111, D = 67,
}
#[derive(Protocol, Debug, PartialEq)]
#[protocol(discriminant = "integer")]
#[repr(u8)] // Force discriminators to be 8-bit.
pub enum Hello {
World(String), SolarSystem(String), LocalGroup(String),
#[protocol(discriminator(100))]
Universe(String),
Everything(String),
}
use protocol::{Enum, Parcel};
assert_eq!(111, Numbered::C.discriminator());
assert_eq!(67, Numbered::D.discriminator());
assert_eq!(1, Hello::World("foo".to_owned()).discriminator());
assert_eq!(100, Hello::Universe("foo".to_owned()).discriminator());
assert_eq!(101, Hello::Everything("foo".to_owned()).discriminator());
Modules§
- attributes
- Documentation about the attributes available to
#[derive(Protocol)]
. - hint
- logic
Parcel
type wrappers that implement complex logic.- types
- Contains newtypes over the standard library types that support finer-grained serialization settings.
- util
- Helper functions for dealing with sets or lists of parcels.
- wire
- Stream-based and datagram-based communication implementations.
Macros§
- define_
middleware_ pipeline - Defines a new middleware pipeline that implements
Pipeline
.
Structs§
- Char
TryFrom Error - Copy of CharTryFromError that works in stable rust
- Error
- The Error type.
- Settings
- Defines serialization settings.
- TryFrom
IntError - Copy of TryFromIntError that works in stable rust
Enums§
Traits§
- Enum
- An
enum
type. - High
Level Deprecated - A high level abstraction over a lower-level
Parcel
. - Parcel
- A value which can be read and written.
- Result
Ext - Additional methods for
Result
, for easy interaction with this crate.
Type Aliases§
- Default
Byte Order - The default byte ordering.
- Result
Derive Macros§
- Protocol
- Custom derive to implement
Parcel
for a type that contains otherParcel
able types.