Add documentation to serde_nbt

This commit is contained in:
Ryan 2022-09-01 20:19:42 -07:00
parent 27033c758e
commit 5d8f7a49da
19 changed files with 105 additions and 20 deletions

23
serde_nbt/Cargo.toml Normal file
View file

@ -0,0 +1,23 @@
[package]
name = "serde_nbt"
description = "A Serde library for Minecraft's Named Binary Tag (NBT) format."
documentation = "https://docs.rs/serde_nbt/"
repository = "https://github.com/rj00a/valence/tree/main/serde_nbt"
readme = "README.md"
license = "MIT"
keywords = ["nbt", "minecraft", "serde", "serialization"]
version = "0.1.0"
authors = ["Ryan Johnson <ryanj00a@gmail.com>"]
edition = "2021"
[dependencies]
byteorder = "1.4.3"
cesu8 = "1.1.0"
indexmap = { version = "1.9.1", features = ["serde"] }
serde = "1"
smallvec = { version = "1.9.0", features = ["union"] }
[dev-dependencies]
hematite-nbt = "0.5.2"
serde_json = "1.0.85"
pretty_assertions = "1.2.1"

View file

@ -11,6 +11,33 @@ use crate::{
macro_rules! def_mod {
($index:literal, $mod_name:ident, $display_name:literal, $variant_name:ident) => {
/// Provides (de)serialization support for the NBT type
#[doc = concat!(" \"", $display_name, "\".")]
///
/// This module is intended to be the target of serde's `#[serde(with =
/// "module")]` field attribute.
///
/// The target field must serialize and deserialize as a seq.
///
/// # Examples
///
/// ```
/// use serde::{Deserialize, Serialize};
/// use serde_nbt::binary::to_writer;
///
/// #[derive(Serialize, Deserialize)]
/// struct MyStruct {
/// #[serde(with = "serde_nbt::int_array")]
/// array: Vec<i32>,
/// }
///
/// let s = MyStruct {
/// array: vec![1, 2, 3],
/// };
///
/// let mut buf = Vec::new();
/// to_writer(&mut buf, &s).unwrap();
/// ```
pub mod $mod_name {
use super::*;

View file

@ -11,6 +11,10 @@ mod list;
mod payload;
mod root;
/// Reads uncompressed NBT binary data from the provided reader.
///
/// The name of the root compound is discarded. If you need access to it, see
/// [`Deserializer`].
pub fn from_reader<R, T>(reader: R) -> Result<T, Error>
where
R: Read,

View file

@ -10,14 +10,24 @@ use smallvec::SmallVec;
use crate::binary::de::payload::PayloadDeserializer;
use crate::{Error, Tag, CESU8_DECODE_ERROR};
/// A serde [`Deserializer`] for the binary representation of NBT.
#[non_exhaustive]
pub struct RootDeserializer<R> {
/// The reader to deserialize from.
pub reader: R,
/// The name of the root compound that was deserialized. If
/// [`Self::save_root_name`] is false, then deserialization will not
/// update this value.
pub root_name: String,
/// Whether or not the root name should be saved to [`Self::root_name`]
/// during deserialization.
pub save_root_name: bool,
}
impl<R: Read> RootDeserializer<R> {
/// Constructs a new deserializer
///
/// [`Self::root_name`] is set to the empty string.
pub fn new(reader: R, save_root_name: bool) -> Self {
Self {
reader,

View file

@ -13,6 +13,14 @@ mod root;
mod seq;
mod structs;
/// Writes uncompressed NBT binary data to the provided writer.
///
/// Note that serialization will fail if the provided value does not serialize
/// as a compound (a map or struct). This is because the NBT format requires the
/// root value to be a named compound.
///
/// The name of the root compound will be `""`. If you want to use a different
/// name, see [`Serializer`].
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
where
W: Write,

View file

@ -130,7 +130,7 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
self.value
.serialize(&mut PayloadSerializer::named(self.writer, v))
.map_err(|e| e.field(format!("{v}")))
.map_err(|e| e.field(v))
}
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {

View file

@ -60,7 +60,7 @@ impl<'w, 'n, W: Write + ?Sized> PayloadSerializer<'w, 'n, W> {
match &mut self.state {
State::Named(name) => {
self.writer.write_u8(tag as u8)?;
write_string(&mut *self.writer, *name)?;
write_string(&mut *self.writer, name)?;
}
State::FirstListElement { len, written_tag } => {
self.writer.write_u8(tag as u8)?;

View file

@ -8,13 +8,19 @@ use crate::binary::ser::structs::SerializeStruct;
use crate::binary::ser::{write_string, Impossible};
use crate::{Error, Tag};
/// A serde [`Serializer`] for the binary representation of NBT.
#[non_exhaustive]
pub struct RootSerializer<'n, W> {
/// The writer to serialize to.
pub writer: W,
/// The name of the root compound to serialize.
///
/// The empty string `""` is acceptable.
pub root_name: &'n str,
}
impl<'n, W: Write> RootSerializer<'n, W> {
/// Constructs a new serializer.
pub fn new(writer: W, root_name: &'n str) -> Self {
Self { writer, root_name }
}

View file

@ -5,6 +5,10 @@ use std::{fmt, io};
use serde::{de, ser};
/// Errors that can occur when serializing or deserializing.
///
/// The error type maintains a backtrace through the NBT value which caused the
/// error. This is used in the `Display` impl on the error.
#[derive(Debug)]
pub struct Error {
/// Box this to keep the error as small as possible. We don't want to
@ -50,6 +54,10 @@ impl Error {
self
}
/// Returns an iterator through the nested fields of an NBT compound to the
/// location where the error occurred.
///
/// The iterator's `Item` is the name of the current field.
pub fn trace(
&self,
) -> impl DoubleEndedIterator<Item = &str> + ExactSizeIterator + FusedIterator + Clone + '_

View file

@ -1,3 +1,9 @@
//! A [serde] library for the serialization and deserialization of Minecraft's
//! [Named Binary Tag] (NBT) format.
//!
//! [serde]: https://docs.rs/serde/latest/serde/
//! [Named Binary Tag]: https://minecraft.fandom.com/wiki/NBT_format
use std::fmt;
use std::fmt::{Display, Formatter};
@ -145,8 +151,10 @@ impl Display for Tag {
}
}
/// Error message for cesu-8 decoding failures.
const CESU8_DECODE_ERROR: &str = "could not convert CESU-8 data to UTF-8";
/// The name of the enum used to encode arrays.
const ARRAY_ENUM_NAME: &str = "__array__";
const BYTE_ARRAY_VARIANT_NAME: &str = "__byte_array__";

View file

@ -7,7 +7,12 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{byte_array, int_array, long_array, ArrayType};
/// Represents an arbitrary NBT value.
/// An arbitrary NBT value.
///
/// Note that `Value`s at the root level other than [`Value::Compound`] will
/// fail to serialize because NBT requires that the root value be a compound.
///
/// At the root level you may want to use [`Compound`] instead.
#[derive(Clone, PartialEq, Debug)]
pub enum Value {
Byte(i8),
@ -24,6 +29,9 @@ pub enum Value {
LongArray(Vec<i64>),
}
/// An arbitrary NBT compound.
///
/// This is a convenient type alias for the [`IndexMap`] type.
pub type Compound = IndexMap<String, Value>;
/// An NBT list value.

View file

@ -1,17 +0,0 @@
[package]
name = "valence_nbt"
version = "0.1.0"
edition = "2021"
[dependencies]
byteorder = "1.4.3"
cesu8 = "1.1.0"
indexmap = { version = "1.9.1", features = ["serde"] }
serde = "1"
smallvec = { version = "1.9.0", features = ["union", "const_generics"] }
[dev-dependencies]
hematite-nbt = "0.5"
serde_json = "1.0.85"
pretty_assertions = "1.2.1"