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
//! A library for encoding and decoding Minecraft's [Named Binary Tag] (NBT)
//! format.
//!
//! [Named Binary Tag]: https://minecraft.fandom.com/wiki/NBT_format
//!
//! # Examples
//!
//! Encode NBT data to its binary form. We are using the [`compound!`] macro to
//! conveniently construct [`Compound`] values.
//!
//! ```rust
//! use valence_nbt::{compound, to_binary_writer, List};
//!
//! let c = compound! {
//! "byte" => 5_i8,
//! "string" => "hello",
//! "list_of_float" => List::Float(vec![
//! 3.1415,
//! 2.7182,
//! 1.4142
//! ]),
//! };
//!
//! let mut buf = Vec::new();
//!
//! to_binary_writer(&mut buf, &c, "").unwrap();
//! ```
//!
//! Decode NBT data from its binary form.
//!
//! ```rust
//! use valence_nbt::{compound, from_binary_slice};
//!
//! let some_bytes = [10, 0, 0, 3, 0, 3, 105, 110, 116, 0, 0, 222, 173, 0];
//!
//! let expected_value = compound! {
//! "int" => 0xdead
//! };
//!
//! let (nbt, root_name) = from_binary_slice(&mut some_bytes.as_slice()).unwrap();
//!
//! assert_eq!(nbt, expected_value);
//! assert_eq!(root_name, "");
//! ```
//!
//! # Features
//!
//! - `preserve_order`: Causes the order of fields in [`Compound`]s to be
//! preserved during insertion and deletion at a slight cost to performance.
//! The iterators on `Compound` can then implement [`DoubleEndedIterator`].
#![deny(unsafe_code)]
pub use compound::Compound;
pub use error::Error;
pub use from_binary_slice::from_binary_slice;
pub use to_binary_writer::to_binary_writer;
pub use value::{List, Value};
pub mod compound;
mod error;
mod from_binary_slice;
mod to_binary_writer;
pub mod value;
mod tag;
#[cfg(test)]
mod tests;
/// Maximum recursion depth to prevent overflowing the call stack.
const MAX_DEPTH: usize = 512;
type Result<T> = std::result::Result<T, Error>;
/// A convenience macro for constructing [`Compound`]s.
///
/// Key expressions must implement `Into<String>` while value expressions must
/// implement `Into<Value>`.
///
/// # Examples
///
/// ```
/// use valence_nbt::{compound, List};
///
/// let c = compound! {
/// "byte" => 123_i8,
/// "list_of_int" => List::Int(vec![3, -7, 5]),
/// "list_of_string" => List::String(vec![
/// "foo".to_owned(),
/// "bar".to_owned(),
/// "baz".to_owned()
/// ]),
/// "string" => "aé日",
/// "compound" => compound! {
/// "foo" => 1,
/// "bar" => 2,
/// "baz" => 3,
/// },
/// "int_array" => vec![5, -9, i32::MIN, 0, i32::MAX],
/// "byte_array" => vec![0_i8, 2, 3],
/// "long_array" => vec![123_i64, 456, 789],
/// };
///
/// println!("{c:?}");
/// ```
#[macro_export]
macro_rules! compound {
($($key:expr => $value:expr),* $(,)?) => {
<$crate::Compound as ::std::iter::FromIterator<(::std::string::String, $crate::Value)>>::from_iter([
$(
(
::std::convert::Into::<::std::string::String>::into($key),
::std::convert::Into::<$crate::Value>::into($value)
),
)*
])
}
}