use ser::Serializer;
use serde::{de as serde_de, Deserialize, Serialize};
pub mod borrow;
pub mod de;
pub mod error;
pub mod ser;
pub mod stream;
pub mod value;
mod arrays;
mod input;
#[macro_use]
mod macros;
pub use arrays::*;
pub use value::{from_value, to_value, Value};
#[cfg(test)]
mod test;
use crate::{
de::Deserializer,
error::{Error, Result},
};
use std::{
convert::TryFrom,
fmt::Display,
io::{Read, Write},
};
#[derive(Deserialize, Debug, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "arbitrary1", derive(arbitrary::Arbitrary))]
#[repr(u8)]
pub enum Tag {
End = 0,
Byte = 1,
Short = 2,
Int = 3,
Long = 4,
Float = 5,
Double = 6,
ByteArray = 7,
String = 8,
List = 9,
Compound = 10,
IntArray = 11,
LongArray = 12,
}
impl TryFrom<u8> for Tag {
type Error = ();
fn try_from(value: u8) -> std::result::Result<Self, ()> {
use Tag::*;
Ok(match value {
0 => End,
1 => Byte,
2 => Short,
3 => Int,
4 => Long,
5 => Float,
6 => Double,
7 => ByteArray,
8 => String,
9 => List,
10 => Compound,
11 => IntArray,
12 => LongArray,
13..=u8::MAX => return Err(()),
})
}
}
impl From<Tag> for u8 {
fn from(tag: Tag) -> Self {
match tag {
Tag::End => 0,
Tag::Byte => 1,
Tag::Short => 2,
Tag::Int => 3,
Tag::Long => 4,
Tag::Float => 5,
Tag::Double => 6,
Tag::ByteArray => 7,
Tag::String => 8,
Tag::List => 9,
Tag::Compound => 10,
Tag::IntArray => 11,
Tag::LongArray => 12,
}
}
}
impl Display for Tag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Tag::End => "end",
Tag::Byte => "byte",
Tag::Short => "short",
Tag::Int => "int",
Tag::Long => "long",
Tag::Float => "float",
Tag::Double => "double",
Tag::ByteArray => "byte-array",
Tag::String => "string",
Tag::List => "list",
Tag::Compound => "compound",
Tag::IntArray => "int-array",
Tag::LongArray => "long-array",
};
f.write_str(s)
}
}
pub fn to_bytes<T: Serialize>(v: &T) -> Result<Vec<u8>> {
to_bytes_with_opts(v, Default::default())
}
pub fn to_writer<T: Serialize, W: Write>(writer: W, v: &T) -> Result<()> {
to_writer_with_opts(writer, v, Default::default())
}
#[derive(Default, Clone)]
pub struct SerOpts {
root_name: String,
}
impl SerOpts {
pub fn new() -> Self {
Default::default()
}
pub fn root_name(mut self, root_name: impl Into<String>) -> Self {
self.root_name = root_name.into();
self
}
}
pub fn to_bytes_with_opts<T: Serialize>(v: &T, opts: SerOpts) -> Result<Vec<u8>> {
let mut result = vec![];
let mut serializer = Serializer {
writer: &mut result,
root_name: opts.root_name,
};
v.serialize(&mut serializer)?;
Ok(result)
}
pub fn to_writer_with_opts<T: Serialize, W: Write>(writer: W, v: &T, opts: SerOpts) -> Result<()> {
let mut serializer = Serializer {
writer,
root_name: opts.root_name,
};
v.serialize(&mut serializer)?;
Ok(())
}
pub fn from_bytes<'a, T>(input: &'a [u8]) -> Result<T>
where
T: serde_de::Deserialize<'a>,
{
from_bytes_with_opts(input, Default::default())
}
pub fn from_reader<'de, R, T>(reader: R) -> Result<T>
where
T: serde_de::Deserialize<'de>,
R: Read,
{
let mut deserializer = Deserializer::from_reader(reader, Default::default());
serde_de::Deserialize::deserialize(&mut deserializer)
}
#[derive(Clone)]
pub struct DeOpts {
max_seq_len: usize,
}
impl DeOpts {
pub fn new() -> Self {
Default::default()
}
pub fn max_seq_len(mut self, value: usize) -> Self {
self.max_seq_len = value;
self
}
}
impl Default for DeOpts {
fn default() -> Self {
Self {
max_seq_len: 10_000_000, }
}
}
pub fn from_bytes_with_opts<'a, T>(input: &'a [u8], opts: DeOpts) -> Result<T>
where
T: serde_de::Deserialize<'a>,
{
const GZIP_MAGIC_BYTES: [u8; 2] = [0x1f, 0x8b];
if input.starts_with(&GZIP_MAGIC_BYTES) {
return Err(Error::bespoke(
"from_bytes expects raw NBT, but input appears to be gzipped".to_string(),
));
}
let mut des = Deserializer::from_bytes(input, opts);
let t = T::deserialize(&mut des)?;
Ok(t)
}