protocol/attributes/mod.rs
1//! Documentation about the attributes available to `#[derive(Protocol)]`.
2//!
3//! Here is an example of `#[derive(Protocol)]`.
4//!
5//! ```
6//! #[macro_use] extern crate protocol_derive;
7//!
8//! #[derive(Protocol)]
9//! struct Packet {
10//! version_number: u8,
11//! magic_number: u8,
12//! payload: Vec<u8>,
13//! }
14//! ```
15//!
16//! # Attributes that apply to items
17//!
18//! These attributes apply to structs and enums.
19//!
20//! ## `#[protocol(length_prefix(<kind>(<length prefix field name>)))]`
21//!
22//! This attribute allows variable-sized fields to have their sizes
23//! specified by an arbitrary integer field in the same struct or enum.
24//!
25//! Without this attribute, variable-sized fields default to having 32-bit
26//! unsigned integer length prefixes prefixed immediately before the field
27//! itself.
28//!
29//! ### Length prefix kinds
30//!
31//! #### `bytes`
32//!
33//! When the length prefix type is `bytes`, the length prefix
34//! represents the total number of bytes that make up a field.
35//!
36//! ```
37//! #[macro_use] extern crate protocol_derive;
38//!
39//! #[derive(Protocol)]
40//! pub struct Foo {
41//! /// This field specifes the length of the last field `reason`.
42//! ///
43//! /// When values of this type are read, the size of `reason` is
44//! /// assumed to be `reason_length` bytes.
45//! pub reason_length: u16,
46//! pub other_stuff_inbetween: [u16; 16],
47//! pub thingy: bool,
48//! /// This field
49//! #[protocol(length_prefix(bytes(reason_length)))]
50//! pub reason: String,
51//! }
52//! ```
53//!
54//! #### `elements`
55//!
56//! When the length prefix type is 'elements', the length prefix
57//! represents the number of elements in a collection or list.
58//!
59//! ```
60//! #[macro_use] extern crate protocol_derive;
61//!
62//! #[derive(Protocol)]
63//! pub struct Bar {
64//! /// This field specifes the number of elements in 'data'.
65//! pub reason_length: u16,
66//! pub other_stuff_inbetween: [u16; 16],
67//! pub thingy: bool,
68//! /// This field
69//! #[protocol(length_prefix(elements(reason_length)))]
70//! pub reason: Vec<(u32, u32)>,
71//! }
72//! ```
73//!
74//! # Notes
75//!
76//! This attribute can only be used with named fields. This means structs like
77//! `struct Hello(u32)` cannot be supported. This is because the length prefix
78//! field must be specified by a name, and therefore only items with named fields
79//! can ever have length prefixes.
80//!
81//! ## Length prefixes placed different structs
82//!
83//! It is possible for a field one one struct to specify the length of a field
84//! in another struct, so long as both structs are fields within a parent struct
85//! and the struct defining the length appears earlier than the one whose length
86//! is being described.
87//!
88//! In this case, the length prefix field must be double quoted.
89//!
90//! `#[protocol(length_prefix(bytes("sibling_field.nested_field.value")))]`
91//!
92//! Example:
93//!
94//! ```
95//! #[macro_use] extern crate protocol_derive;
96//!
97//! #[derive(Protocol)]
98//! struct Packet {
99//! /// The length of the adjacent 'reason' field is nested under this field.
100//! pub packet_header: PacketHeader,
101//! /// The length of this field is specified by the packet header.
102//! #[protocol(length_prefix(bytes("packet_header.reason_length")))]
103//! pub reason: String,
104//! }
105//!
106//! #[derive(Protocol)]
107//! pub struct PacketHeader {
108//! pub reason_length: u16,
109//! }
110//! ```
111