use std::ops::{Deref, DerefMut};
use byteorder::{BigEndian, ReadBytesExt};
use serde::{de::Visitor, Deserialize, Serialize};
use serde_bytes::ByteBuf;
pub(crate) const BYTE_ARRAY_TOKEN: &str = "__fastnbt_byte_array";
pub(crate) const INT_ARRAY_TOKEN: &str = "__fastnbt_int_array";
pub(crate) const LONG_ARRAY_TOKEN: &str = "__fastnbt_long_array";
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "arbitrary1", derive(arbitrary::Arbitrary))]
pub struct ByteArray {
data: Vec<i8>,
}
impl Serialize for ByteArray {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[derive(Serialize)]
struct Inner {
__fastnbt_byte_array: ByteBuf,
}
Inner {
__fastnbt_byte_array: ByteBuf::from(self.to_bytes()),
}
.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ByteArray {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct InnerVisitor;
impl<'de> Visitor<'de> for InnerVisitor {
type Value = ByteArray;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("byte array")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let token = map.next_key::<&str>()?.ok_or_else(|| {
serde::de::Error::custom("expected NBT byte array token, but got empty map")
})?;
let data = map.next_value::<ByteBuf>()?;
if token == BYTE_ARRAY_TOKEN {
Ok(ByteArray::from_buf(data.into_vec()))
} else {
Err(serde::de::Error::custom("expected NBT byte array token"))
}
}
}
deserializer.deserialize_map(InnerVisitor)
}
}
impl ByteArray {
pub fn new(data: Vec<i8>) -> Self {
Self { data }
}
pub fn into_inner(self) -> Vec<i8> {
self.data
}
pub(crate) fn from_bytes(data: &[u8]) -> Self {
let data = unsafe { &*(data as *const [u8] as *const [i8]) };
ByteArray {
data: data.to_owned(),
}
}
pub(crate) fn from_buf(data: Vec<u8>) -> Self {
let data = data.as_slice();
let data = unsafe { &*(data as *const [u8] as *const [i8]) };
ByteArray {
data: data.to_owned(),
}
}
pub(crate) fn to_bytes(&self) -> Vec<u8> {
self.data.iter().flat_map(|i| i.to_be_bytes()).collect()
}
}
impl Deref for ByteArray {
type Target = [i8];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl DerefMut for ByteArray {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "arbitrary1", derive(arbitrary::Arbitrary))]
pub struct IntArray {
data: Vec<i32>,
}
impl IntArray {
pub fn new(data: Vec<i32>) -> Self {
Self { data }
}
pub fn into_inner(self) -> Vec<i32> {
self.data
}
pub(crate) fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
let data = data
.chunks_exact(4)
.map(|mut bs| bs.read_i32::<BigEndian>())
.collect::<std::io::Result<Vec<i32>>>()?;
Ok(IntArray { data })
}
pub(crate) fn to_bytes(&self) -> Vec<u8> {
self.data.iter().flat_map(|i| i.to_be_bytes()).collect()
}
}
impl Serialize for IntArray {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[derive(Serialize)]
struct Inner {
__fastnbt_int_array: ByteBuf,
}
Inner {
__fastnbt_int_array: ByteBuf::from(self.to_bytes()),
}
.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for IntArray {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct InnerVisitor;
impl<'de> Visitor<'de> for InnerVisitor {
type Value = IntArray;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("int array")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let token = map.next_key::<&str>()?.ok_or_else(|| {
serde::de::Error::custom("expected NBT int array token, but got empty map")
})?;
let data = map.next_value::<ByteBuf>()?;
match token {
INT_ARRAY_TOKEN => IntArray::from_bytes(&data)
.map_err(|_| serde::de::Error::custom("could not read i32 for int array")),
_ => Err(serde::de::Error::custom("expected NBT int array token")),
}
}
}
deserializer.deserialize_map(InnerVisitor)
}
}
impl Deref for IntArray {
type Target = [i32];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl DerefMut for IntArray {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "arbitrary1", derive(arbitrary::Arbitrary))]
pub struct LongArray {
data: Vec<i64>,
}
impl LongArray {
pub fn new(data: Vec<i64>) -> Self {
Self { data }
}
pub fn into_inner(self) -> Vec<i64> {
self.data
}
pub(crate) fn from_bytes(data: &[u8]) -> std::io::Result<Self> {
let data = data
.chunks_exact(8)
.map(|mut bs| bs.read_i64::<BigEndian>())
.collect::<std::io::Result<Vec<i64>>>()?;
Ok(LongArray { data })
}
pub(crate) fn to_bytes(&self) -> Vec<u8> {
self.data.iter().flat_map(|i| i.to_be_bytes()).collect()
}
}
impl Serialize for LongArray {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[derive(Serialize)]
struct Inner {
__fastnbt_long_array: ByteBuf,
}
Inner {
__fastnbt_long_array: ByteBuf::from(self.to_bytes()),
}
.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for LongArray {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct InnerVisitor;
impl<'de> Visitor<'de> for InnerVisitor {
type Value = LongArray;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("long array")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let token = map.next_key::<&str>()?.ok_or_else(|| {
serde::de::Error::custom("expected NBT long array token, but got empty map")
})?;
let data = map.next_value::<ByteBuf>()?;
match token {
LONG_ARRAY_TOKEN => LongArray::from_bytes(&data)
.map_err(|_| serde::de::Error::custom("could not read i64 for long array")),
_ => Err(serde::de::Error::custom("expected NBT long array token")),
}
}
}
deserializer.deserialize_map(InnerVisitor)
}
}
impl Deref for LongArray {
type Target = [i64];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl DerefMut for LongArray {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}