na_nbt 0.2.1

High-performance NBT (Named Binary Tag) library with zero-copy parsing and serde support
Documentation
use std::{marker::PhantomData, ptr, slice};

use zerocopy::byteorder;

use crate::{
    ByteOrder, CompoundBase, CompoundMut, ConfigMut, ConfigRef, MUTF8Str, VecMut, TagID, cold_path,
    mutable::{
        compound_ref::RefCompoundIter, config::MutableConfig, size::mutable_tag_size,
        string_ref::RefString, value_mut::MutValue,
    },
};

#[repr(transparent)]
pub struct MutCompound<'s, O: ByteOrder> {
    pub(crate) data: VecMut<'s, u8>,
    pub(crate) _marker: PhantomData<O>,
}

impl<'s, O: ByteOrder> IntoIterator for MutCompound<'s, O> {
    type Item = (RefString<'s>, MutValue<'s, O>);
    type IntoIter = MutCompoundIter<'s, O>;

    #[inline]
    fn into_iter(mut self) -> Self::IntoIter {
        MutCompoundIter {
            data: self.data.as_mut_ptr(),
            _marker: PhantomData,
        }
    }
}

impl<'s, O: ByteOrder> CompoundBase for MutCompound<'s, O> {}

impl<'s, O: ByteOrder> CompoundMut<'s> for MutCompound<'s, O> {
    type Config = MutableConfig<O>;

    #[inline]
    fn _to_read_params<'a>(&'a self) -> <Self::Config as ConfigRef>::ReadParams<'a>
    where
        's: 'a,
    {
        self.data.as_ptr()
    }

    #[inline]
    fn _to_write_params<'a>(&'a mut self) -> <Self::Config as ConfigMut>::WriteParams<'a>
    where
        's: 'a,
    {
        unsafe { self.data.new_clone() }
    }

    #[inline]
    fn iter<'a>(&'a self) -> <Self::Config as ConfigRef>::CompoundIter<'a>
    where
        's: 'a,
    {
        RefCompoundIter {
            data: self.data.as_ptr(),
            _marker: PhantomData,
        }
    }

    #[inline]
    fn iter_mut<'a>(&'a mut self) -> <Self::Config as ConfigMut>::CompoundIterMut<'a>
    where
        's: 'a,
    {
        MutCompoundIter {
            data: self.data.as_mut_ptr(),
            _marker: PhantomData,
        }
    }
}
pub struct MutCompoundIter<'s, O: ByteOrder> {
    data: *mut u8,
    _marker: PhantomData<(&'s (), O)>,
}

impl<'s, O: ByteOrder> Default for MutCompoundIter<'s, O> {
    #[inline]
    fn default() -> Self {
        Self {
            data: ptr::null_mut(),
            _marker: PhantomData,
        }
    }
}

unsafe impl<'s, O: ByteOrder> Send for MutCompoundIter<'s, O> {}
unsafe impl<'s, O: ByteOrder> Sync for MutCompoundIter<'s, O> {}

impl<'s, O: ByteOrder> Iterator for MutCompoundIter<'s, O> {
    type Item = (RefString<'s>, MutValue<'s, O>);

    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            let tag_id = *self.data.cast();

            if tag_id == TagID::End {
                cold_path();
                return None;
            }

            let name_len = byteorder::U16::<O>::from_bytes(*self.data.add(1).cast()).get();
            let name = RefString {
                data: MUTF8Str::from_mutf8_unchecked(slice::from_raw_parts(
                    self.data.add(3),
                    name_len as usize,
                )),
            };

            let value = <MutableConfig<O> as ConfigMut>::read_value_mut(
                tag_id,
                self.data.add(3 + name_len as usize),
            );

            self.data = self
                .data
                .add(3 + name_len as usize + mutable_tag_size(tag_id));

            Some((name, value))
        }
    }
}