1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
//! 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());
//!
//! ```
pub use self::enum_ty::Enum;
pub use self::parcel::Parcel;
pub use self::errors::{Error, ErrorKind, Result, ResultExt, CharTryFromError, TryFromIntError};
#[cfg(feature = "high-level-trait")] #[allow(deprecated)] pub use self::high_level::HighLevel;
pub use self::settings::*;
/// Custom derive to implement `Parcel` for a type that contains other `Parcel`able types.
///
/// Example:
///
/// ```
/// #[derive(protocol::Protocol)]
/// struct Hello {
/// foo: u8,
/// bar: String,
/// }
/// ```
#[cfg(feature = "derive")]
pub use protocol_derive::Protocol;
mod settings;
#[macro_use]
pub mod types;
#[macro_use]
pub mod wire;
pub mod attributes;
mod enum_ty;
mod errors;
#[cfg(feature = "high-level-trait")] mod high_level;
pub mod hint;
pub mod logic;
mod parcel;
pub mod util;
extern crate byteorder;
#[macro_use]
extern crate error_chain;
#[cfg(feature = "uuid")]
extern crate uuid;
extern crate num_traits;
/// The default byte ordering.
pub type DefaultByteOrder = ::byteorder::BigEndian;