Crate protocol[][src]

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 Parcels.

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

CharTryFromError

Copy of CharTryFromError that works in stable rust

Error

The Error type.

Settings

Defines serialization settings.

TryFromIntError

Copy of TryFromIntError that works in stable rust

Enums

ByteOrder

Specifies the byte order of data transfer.

ErrorKind

The kind of an error.

Traits

Enum

An enum type.

HighLevel

A high level abstraction over a lower-level Parcel.

Parcel

A value which can be read and written.

ResultExt

Additional methods for Result, for easy interaction with this crate.

Type Definitions

DefaultByteOrder

The default byte ordering.