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
//! An encoder for bencode. Guarantees that the output string is valid bencode //! //! # Encoding a structure //! //! The easiest way to encode a structure is to implement [`ToBencode`] for it. For most structures, //! this should be very simple: //! //! ``` //! # use bendy::encoding::{ToBencode, SingleItemEncoder, Error}; //! //! struct Message { //! foo: i32, //! bar: String, //! } //! //! impl ToBencode for Message { //! // Atoms have depth one. The struct wrapper adds one level to that //! const MAX_DEPTH: usize = 1; //! //! fn encode(&self, encoder: SingleItemEncoder) -> Result<(), Error> { //! encoder.emit_dict(|mut e| { //! // Use e to emit the values //! e.emit_pair(b"bar", &self.bar)?; //! e.emit_pair(b"foo", &self.foo) //! })?; //! Ok(()) //! } //! } //! # //! # fn main() -> Result<(), Error> { //! # let message = Message{ //! # foo: 1, //! # bar: "quux".to_string(), //! # }; //! # //! # message.to_bencode().map(|_| ()) //! # } //! ``` //! //! Then, messages can be serialized using [`ToBencode::to_bencode`]: //! //! ``` //! # use bendy::encoding::{ToBencode, SingleItemEncoder, Error}; //! # //! # struct Message { //! # foo: i32, //! # bar: String, //! # } //! # //! # impl ToBencode for Message { //! # // Atoms have depth zero. The struct wrapper adds one level to that //! # const MAX_DEPTH: usize = 1; //! # //! # fn encode(&self, encoder: SingleItemEncoder) -> Result<(), Error> { //! # encoder.emit_dict(|mut e| { //! # // Use e to emit the values. They must be in sorted order here. //! # // If sorting the dict first is annoying, you can also use //! # // encoder.emit_and_sort_dict //! # e.emit_pair(b"bar", &self.bar)?; //! # e.emit_pair(b"foo", &self.foo) //! # })?; //! # Ok(()) //! # } //! # } //! # //! # fn main() -> Result<(), Error> { //! let message = Message { //! foo: 1, //! bar: "quux".to_string(), //! }; //! //! message.to_bencode() //! # .map(|_| ()) //! # } //! ``` //! //! Most primitive types already implement [`ToBencode`]. //! //! # Nesting depth limits //! //! To allow this to be used on limited platforms, all implementations of [`ToBencode`] include a //! maximum nesting depth. Atoms (integers and byte strings) are considered to have depth 0. An //! object (a list or dict) containing only atoms has depth 1, and in general, an object has a depth //! equal to the depth of its deepest member plus one. In some cases, an object doesn't have a //! statically known depth. For example, ASTs may be arbitrarily nested. Such objects should //! have their depth set to 0, and callers should construct the Encoder manually, adding an //! appropriate buffer for the depth: //! //! ``` //! # use bendy::encoding::{ToBencode, Encoder, Error}; //! # //! # type ObjectType = u32; //! # static OBJECT: u32 = 0; //! # //! # fn main() -> Result<(), Error> { //! let mut encoder = Encoder::new().with_max_depth(ObjectType::MAX_DEPTH + 10); //! //! encoder.emit(OBJECT)?; //! encoder.get_output() //! # .map_err(Error::from) //! # .map(|_| ()) // ignore a success return value //! # } //! ``` //! //! # Error handling //! //! Once an error occurs during encoding, all future calls to the same encoding stream will fail //! early with the same error. It is not defined whether any callback or implementation of //! [`ToBencode::encode`] is called before returning an error; such callbacks should //! respond to failure by bailing out as quickly as possible. //! //! Not all values in [`Error`] can be caused by an encoding operation. Specifically, you only need //! to worry about [`UnsortedKeys`] and [`NestingTooDeep`]. //! //! [`ToBencode::encode`]: self::ToBencode::encode //! [`UnsortedKeys`]: self::Error#UnsortedKeys //! [`NestingTooDeep`]: self::Error#NestingTooDeep mod encoder; mod error; mod printable_integer; mod to_bencode; pub use self::{ encoder::{Encoder, SingleItemEncoder, SortedDictEncoder, UnsortedDictEncoder}, error::Error, printable_integer::PrintableInteger, to_bencode::{AsString, ToBencode}, };