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
//! Documentation about the attributes available to `#[derive(Protocol)]`. //! //! Here is an example of `#[derive(Protocol)]`. //! //! ``` //! #[macro_use] extern crate protocol_derive; //! //! #[derive(Protocol)] //! struct Packet { //! version_number: u8, //! magic_number: u8, //! payload: Vec<u8>, //! } //! ``` //! //! # Attributes that apply to items //! //! These attributes apply to structs and enums. //! //! ## `#[protocol(length_prefix(<kind>(<length prefix field name>)))]` //! //! This attribute allows variable-sized fields to have their sizes //! specified by an arbitrary integer field in the same struct or enum. //! //! Without this attribute, variable-sized fields default to having 32-bit //! unsigned integer length prefixes prefixed immediately before the field //! itself. //! //! ### Length prefix kinds //! //! #### `bytes` //! //! When the length prefix type is `bytes`, the length prefix //! represents the total number of bytes that make up a field. //! //! ``` //! #[macro_use] extern crate protocol_derive; //! //! #[derive(Protocol)] //! pub struct Foo { //! /// This field specifes the length of the last field `reason`. //! /// //! /// When values of this type are read, the size of `reason` is //! /// assumed to be `reason_length` bytes. //! pub reason_length: u16, //! pub other_stuff_inbetween: [u16; 16], //! pub thingy: bool, //! /// This field //! #[protocol(length_prefix(bytes(reason_length)))] //! pub reason: String, //! } //! ``` //! //! #### `elements` //! //! When the length prefix type is 'elements', the length prefix //! represents the number of elements in a collection or list. //! //! ``` //! #[macro_use] extern crate protocol_derive; //! //! #[derive(Protocol)] //! pub struct Bar { //! /// This field specifes the number of elements in 'data'. //! pub reason_length: u16, //! pub other_stuff_inbetween: [u16; 16], //! pub thingy: bool, //! /// This field //! #[protocol(length_prefix(elements(reason_length)))] //! pub reason: Vec<(u32, u32)>, //! } //! ``` //! //! # Notes //! //! This attribute can only be used with named fields. This means structs like //! `struct Hello(u32)` cannot be supported. This is because the length prefix //! field must be specified by a name, and therefore only items with named fields //! can ever have length prefixes. //! //! ## Length prefixes placed different structs //! //! It is possible for a field one one struct to specify the length of a field //! in another struct, so long as both structs are fields within a parent struct //! and the struct defining the length appears earlier than the one whose length //! is being described. //! //! In this case, the length prefix field must be double quoted. //! //! `#[protocol(length_prefix(bytes("sibling_field.nested_field.value")))]` //! //! Example: //! //! ``` //! #[macro_use] extern crate protocol_derive; //! //! #[derive(Protocol)] //! struct Packet { //! /// The length of the adjacent 'reason' field is nested under this field. //! pub packet_header: PacketHeader, //! /// The length of this field is specified by the packet header. //! #[protocol(length_prefix(bytes("packet_header.reason_length")))] //! pub reason: String, //! } //! //! #[derive(Protocol)] //! pub struct PacketHeader { //! pub reason_length: u16, //! } //! ```