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
//! # Named Binary Tag (NBT) //! The The Named Binary Tag, is a structured binary format used by the game Minecraft for a variety //! of purposes such as, Player Data and World Saves as well as being used within the Minecraft Protocol. //! //! [NBT Specification](https://wiki.vg/NBT#Specification) //! //! ## This Crate //! This crate is __yet__ another implementation of the NBT format. //! //! ### Key features //! - Support for Serialisation and Deserialization with the [Serde](https://serde.rs) framework. //! - Ability to create partial or complete documents through the `Tag` and `Blob` objects. //! - Ability to read/write from a socket or buffer. //! //! ### Cargo Features //! - `with_serde` (default) includes Serde serialisation and deserialization support. //! - `serde_boolean` converts booleans to bytes during serialisation and deserialization. //! - `serde_unsigned` converts unsigned to their signed counterparts during serialisation and deserialization. //! - `arrays` utils for writing byte, int and long arrays. (dev branch) //! - `compression` gzip and DEFLATE support. (dev branch) //! //! ### Operation //! This crate has two seperate operations that allow data to be mutated. //! 1. Read/Writing - `Tags/Blobs` `<--NBT-->` `Bytes/Buffer` //! 2. Encoding/Decoding - `Tags/Blobs` `<--Serde-->` `Structs` //! //! ## Quick Start //! //! #### Tags //! One way of creating partial NBT objects is with tags. //! ``` //! use nbt::Tag; //! //! // An example of a TAG_Byte with value 42. //! let byte = Tag::Byte(42); //! //! // An example of a TAG_String with value "Hello!" //! let string = Tag::String("Hello!".to_string()); //! //! // An example of TAG_List containing bytes, with values of [1,2,3] //! let list = Tag::List(vec![Tag::Byte(1), Tag::Byte(2), Tag::Byte(3)]); //! //! // An example of a compound //! use std::collections::HashMap; //! let mut map = HashMap::<String, Tag>::new(); //! map.insert("age".to_string(), Tag::Byte(18)); //! map.insert("id".to_string(), Tag::Int(69420)); //! let compound = Tag::Compound(map); //! ``` //! #### Blobs //! Blobs allow for you to create full NBT objects/documents. //! ``` //! use nbt::{Blob, Tag}; //! //! // Creating a blob //! let mut blob = Blob::new(); //! //! // Inserting a tag //! blob.insert("age", Tag::Byte(18)); //! //! // Using the ToTag trait to insert a tag. //! blob.insert("id", 69420_i32); //! ``` //! Blobs reprsent the root compound, and hence can be named. //! //! When a name is not specifed it defaults to `""` //! ``` //! use nbt::{Blob}; //! //! // Creating a blob with a name //! let mut blob = Blob::create("user"); //! blob.insert("name", "pokechu22"); //! ``` //! //! #### Encoding / Writing //! You can encode a partial or full NBT object using the `NBTWrite` trait. //! ``` //! use nbt::{Tag, NBTWrite}; //! let tag = Tag::Float(69.420); //! //! // Writing to a buffer //! let mut buffer = Vec::new(); //! tag.write(&mut buffer).unwrap(); //! //! // Outputting to a Vec. //! let bytes = tag.bytes().unwrap(); //! //! println!("{:?}", bytes); //! ``` //! //! #### Decoding / Reading //! ``` //! use nbt::{Tag, NBTWrite, NBTRead}; //! let data = /* vec![...] */ //! # vec![10, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 8, 0, 4, 110, 97, 109, 101, 0, 9, 66, 97, 110, 97, 110, 114, 97, 109, 97, 0]; //! //! // Reading from a buffer //! use std::io::Cursor; //! let mut cursor = Cursor::new(data.clone()); //! let one = Tag::read(&mut cursor).unwrap(); //! // Also works for: Blob::read(...) //! //! // Reading from vec //! let two = Tag::from_bytes(data); //! // Also works for: Blob::from_bytes(...) //! ``` //! //! ### Serde //! This library has full serde serialisation and deserialization support for all types in the //! [serde data model](https://serde.rs/data-model.html) except for u8 (byte)arrays. //! //! Serde support requires the `with_serde` cargo feature, which is enabled by default. //! //! #### Encoding //! Here is an basic example for encoding between a struct and bytes //! ```rust //! use serde::Serialize; //! use nbt::{encode, NBTWrite}; //! //! // Define a Serializable struct //! #[derive(Serialize)] //! pub struct HelloWorld { //! name: String //! } //! //! // Instantiate //! let hello = HelloWorld { //! name: "Dinnerbone".to_string() //! }; //! //! // Encode/Serialise the struct into a blob. //! let blob = encode(&hello).unwrap(); //! //! // get the bytes from the blob. //! let bytes = blob.bytes().unwrap(); //! //! assert_eq!(bytes, vec![10, 0, 0, 8, 0, 4, 110, 97, 109, 101, 0, 10, 68, 105, 110, 110, 101, 114, 98, 111, 110, 101, 0]) //! ``` //! //! #### Decoding //! Here is the reverse operation for the above example //! ``` //! use serde::Deserialize; //! use nbt::{Blob, NBTRead, decode}; //! //! // Define a Deserialisable struct //! #[derive(Deserialize, PartialEq, Debug)] //! pub struct HelloWorld { //! name: String //! } //! //! // Bytes //! let bytes = vec![10, 0, 0, 8, 0, 4, 110, 97, 109, 101, 0, 10, 68, 105, 110, 110, 101, 114, 98, 111, 110, 101, 0]; //! //! // Create a blob from bytes //! let blob = Blob::from_bytes(bytes).unwrap(); //! //! // Deserialize the blob into the struct //! let hello = decode::<HelloWorld>(blob).unwrap(); //! //! assert_eq!(hello, HelloWorld { //! name: "Dinnerbone".to_string() //! }); //! ``` //! //! #### Serde Functions //! - `BLOB --> SERDE` [`decode(...)`](crate::decode()) //! - `BLOB <-- SERDE` [`encode(...)`](crate::encode()) //! - `TAG --> SERDE` [`decode_tag(...)`](crate::decode_tag) //! - `TAG <-- SERDE` [`encode_tag(...)`](crate::encode_tag) //! - `BLOB --> SERDE + NAME` [`decode_named(...)`](crate::decode_named) //! - `BLOB <-- SERDE + NAME` [`encode_named(...)`](crate::encode_named) pub(crate) mod tags; pub(crate) mod error; pub(crate) mod blob; pub(crate) mod encode; pub(crate) mod decode; pub(crate) mod front; pub(crate) mod util; pub use util::{FromTag, ToTag}; pub use front::{NBTWrite, NBTRead}; pub use blob::Blob; pub use tags::{TagIdent, Tag}; #[cfg(test)] pub mod tests; #[cfg(feature="with_serde")] mod ser; #[cfg(feature="with_serde")] mod de; #[cfg(feature="with_serde")] pub use front::{encode, encode_named, encode_tag, decode, decode_named, decode_tag};