djin_protocol/
lib.rs

1//! Simple packet-based protocol definitions in Rust.
2//!
3//! * The `Parcel` trait defines any type that can be serialized
4//!   to a connection.
5//! * The `wire` module deals with transmission of `Parcel`s.
6//!
7//! # Examples
8//!
9//! ## Get the raw bytes representing a parcel.
10//!
11//! ```
12//! extern crate djin_protocol;
13//! #[macro_use] extern crate djin_protocol_derive;
14//! #[derive(Protocol, Debug, PartialEq)]
15//! pub struct Health(pub u8);
16//!
17//! #[derive(Protocol, Debug, PartialEq)]
18//! pub struct Player {
19//!     pub name: String,
20//!     pub health: Health,
21//!     pub position: (i16, i16, i16),
22//!     pub velocity: (i16, i16, i16),
23//! }
24//!
25//! use djin_protocol::Parcel;
26//!
27//! assert_eq!(vec![
28//!     0, 0, 0, 3, // "Bob" string length prefix
29//!     b'B', b'o', b'b', // The string "Bob".
30//!     100, // The health byte.
31//!     0, 10, 0, 81, 255, 151, // 2-byte x-position, y-position, and z-position.
32//!     0, 0, 0, 0, 0, 0, // 2-byte x-velocity, y-velocity, and z-velocity.
33//! ], Player {
34//!     name: "Bob".to_owned(),
35//!     health: Health(100),
36//!     position: (10, 81, -105),
37//!     velocity: (0, 0, 0),
38//! }.raw_bytes(&djin_protocol::Settings::default()).unwrap());
39//! ```
40//!
41//! ## Enums
42//!
43//! Every enum has a value for each variant used to distinguish
44//! between each variant. This can be as simple as a 32-bit integer
45//! representing the variant's index. This is called the discriminator.
46//!
47//! ### String discriminators
48//!
49//! ```
50//! extern crate djin_protocol;
51//! #[macro_use] extern crate djin_protocol_derive;
52//! // This enum, like all enums, defaults to using String discriminators.
53//! #[derive(Protocol, Debug, PartialEq)]
54//! enum Foo { A, B, C }
55//!
56//! // This enum explicitly specifies a string discriminant.
57//! //
58//! // This is the default anyway and thus it is identical in layout
59//! // to the previous enum.
60//! #[derive(Protocol, Debug, PartialEq)]
61//! #[protocol(discriminant = "string")]
62//! enum Bar { A, B, C }
63//! ```
64//!
65//! By default, enums have `String` discriminators. This means that
66//! when serializing enum values to and from bytes, unless otherwise
67//! specified the variant's full name will be transmitted as a string.
68//!
69//! This allows variants to be added, modified, or reordered in
70//! a backwards-compatible way.
71//!
72//! ### Integer discriminators
73//!
74//! ```
75//! extern crate djin_protocol;
76//! #[macro_use] extern crate djin_protocol_derive;
77//! // An enum with integer discriminators.
78//! #[derive(Protocol, Debug, PartialEq)]
79//! #[protocol(discriminant = "integer")]
80//! enum Baz {
81//!     Fizz = 0, // override the default first discriminator of 1
82//!     Buzz, // defaults to `prior discriminator + 1`, therefore has a discriminator of 1.
83//!     Bing, // defaults to `prior discriminator + 1`, therefore has a discriminator of 2.
84//!     Boo = 1234,
85//!     Beez, // defaults to `prior discriminator + 1`, therefore has a discriminator of 1235.
86//! }
87//!
88//! use djin_protocol::{Enum, Parcel};
89//!
90//! // By default, integer discriminators are 32-bits.
91//! assert_eq!([0u8, 0, 0, 2], &Baz::Bing.discriminator().raw_bytes(&djin_protocol::Settings::default()).unwrap()[..]);
92//!
93//! assert_eq!(0, Baz::Fizz.discriminator());
94//! assert_eq!(1, Baz::Buzz.discriminator());
95//! assert_eq!(2, Baz::Bing.discriminator());
96//! assert_eq!(1234, Baz::Boo.discriminator());
97//! assert_eq!(1235, Baz::Beez.discriminator());
98//! ```
99//!
100//! It is possible to set the underlying integer type via the `#[repr(<type>)]` attribute.
101//!
102//! ```
103//! extern crate djin_protocol;
104//! #[macro_use] extern crate djin_protocol_derive;
105//! #[derive(Protocol, Debug, PartialEq)]
106//! #[protocol(discriminant = "integer")]
107//! #[repr(u8)] // Force discriminators to be 8-bit.
108//! pub enum Hello {
109//!     World(String), SolarSystem(String), LocalGroup(String),
110//!     Universe(String), Everything(String),
111//! }
112//!
113//! use djin_protocol::{Enum, Parcel};
114//!
115//! assert_eq!([2, // 1-byte discriminator
116//!             0, 0, 0, 3, // string length
117//!             b'f', b'o', b'o', // the string
118//!             ], &Hello::SolarSystem("foo".to_owned()).raw_bytes(&djin_protocol::Settings::default()).unwrap()[..]);
119//! ```
120//!
121//! Discriminators can be overriden on a per-variant basis via
122//! the `#[protocol(discriminator(<value>))]` attribute.
123//!
124//! In the case of trivial enums with no fields,
125//! the `Variant = <discriminator>` syntax may be used.
126//!
127//! ```
128//! extern crate djin_protocol;
129//! #[macro_use] extern crate djin_protocol_derive;
130//! #[derive(Protocol, Debug, PartialEq)]
131//! #[protocol(discriminant = "integer")]
132//! #[repr(u8)] // Force discriminators to be 8-bit.
133//! enum Numbered {
134//!     A = 1, B = 2, C = 111, D = 67,
135//! }
136//!
137//! #[derive(Protocol, Debug, PartialEq)]
138//! #[protocol(discriminant = "integer")]
139//! #[repr(u8)] // Force discriminators to be 8-bit.
140//! pub enum Hello {
141//!     World(String), SolarSystem(String), LocalGroup(String),
142//!     #[protocol(discriminator(100))]
143//!     Universe(String),
144//!     Everything(String),
145//! }
146//!
147//! use djin_protocol::{Enum, Parcel};
148//!
149//! assert_eq!(111, Numbered::C.discriminator());
150//! assert_eq!(67, Numbered::D.discriminator());
151//!
152//! assert_eq!(1, Hello::World("foo".to_owned()).discriminator());
153//! assert_eq!(100, Hello::Universe("foo".to_owned()).discriminator());
154//! assert_eq!(101, Hello::Everything("foo".to_owned()).discriminator());
155//!
156//! ```
157
158pub use self::enum_ty::Enum;
159pub use self::parcel::Parcel;
160pub use self::errors::{Error, ErrorKind, ResultExt, CharTryFromError, TryFromIntError};
161pub use self::high_level::HighLevel;
162pub use self::settings::*;
163
164mod settings;
165#[macro_use]
166pub mod types;
167#[macro_use]
168pub mod wire;
169
170pub mod attributes;
171mod enum_ty;
172mod errors;
173mod high_level;
174pub mod hint;
175pub mod logic;
176mod parcel;
177pub mod util;
178
179
180extern crate byteorder;
181extern crate flate2;
182#[macro_use]
183extern crate error_chain;
184
185#[cfg(feature = "uuid")]
186extern crate uuid;
187extern crate num_traits;
188
189/// The default byte ordering.
190pub type DefaultByteOrder = ::byteorder::BigEndian;
191