use std::marker::PhantomData;
use zerocopy::byteorder;
use crate::{
ByteOrder, MapRef, NBT, TagID, ValueBase, ValueRef, VisitRef,
immutable::{
array::ReadonlyArray, compound::ReadonlyCompound, config::ImmutableConfig,
document::Document, list::ReadonlyList, string::ReadonlyString,
typed_list::ReadonlyTypedList,
},
};
#[derive(Clone)]
pub enum ReadonlyValue<'doc, O: ByteOrder, D: Document> {
End(()),
Byte(i8),
Short(i16),
Int(i32),
Long(i64),
Float(f32),
Double(f64),
ByteArray(ReadonlyArray<'doc, i8, D>),
String(ReadonlyString<'doc, D>),
List(ReadonlyList<'doc, O, D>),
Compound(ReadonlyCompound<'doc, O, D>),
IntArray(ReadonlyArray<'doc, byteorder::I32<O>, D>),
LongArray(ReadonlyArray<'doc, byteorder::I64<O>, D>),
}
impl<'doc, O: ByteOrder, D: Document> Default for ReadonlyValue<'doc, O, D> {
#[inline]
fn default() -> Self {
ReadonlyValue::End(())
}
}
impl<'doc, O: ByteOrder, D: Document> ValueBase for ReadonlyValue<'doc, O, D> {
#[inline]
fn tag_id(&self) -> TagID {
match self {
ReadonlyValue::End(_) => TagID::End,
ReadonlyValue::Byte(_) => TagID::Byte,
ReadonlyValue::Short(_) => TagID::Short,
ReadonlyValue::Int(_) => TagID::Int,
ReadonlyValue::Long(_) => TagID::Long,
ReadonlyValue::Float(_) => TagID::Float,
ReadonlyValue::Double(_) => TagID::Double,
ReadonlyValue::ByteArray(_) => TagID::ByteArray,
ReadonlyValue::String(_) => TagID::String,
ReadonlyValue::List(_) => TagID::List,
ReadonlyValue::Compound(_) => TagID::Compound,
ReadonlyValue::IntArray(_) => TagID::IntArray,
ReadonlyValue::LongArray(_) => TagID::LongArray,
}
}
}
impl<'doc, O: ByteOrder, D: Document> ValueRef<'doc> for ReadonlyValue<'doc, O, D> {
type Config = ImmutableConfig<O, D>;
fn visit<'a, R>(&'a self, match_fn: impl FnOnce(VisitRef<'a, 'doc, Self::Config>) -> R) -> R
where
'doc: 'a,
{
match self {
ReadonlyValue::End(value) => match_fn(VisitRef::End(value)),
ReadonlyValue::Byte(value) => match_fn(VisitRef::Byte(value)),
ReadonlyValue::Short(value) => match_fn(VisitRef::Short(value)),
ReadonlyValue::Int(value) => match_fn(VisitRef::Int(value)),
ReadonlyValue::Long(value) => match_fn(VisitRef::Long(value)),
ReadonlyValue::Float(value) => match_fn(VisitRef::Float(value)),
ReadonlyValue::Double(value) => match_fn(VisitRef::Double(value)),
ReadonlyValue::ByteArray(value) => match_fn(VisitRef::ByteArray(value)),
ReadonlyValue::String(value) => match_fn(VisitRef::String(value)),
ReadonlyValue::List(value) => match_fn(VisitRef::List(value)),
ReadonlyValue::Compound(value) => match_fn(VisitRef::Compound(value)),
ReadonlyValue::IntArray(value) => match_fn(VisitRef::IntArray(value)),
ReadonlyValue::LongArray(value) => match_fn(VisitRef::LongArray(value)),
}
}
fn map<R>(self, match_fn: impl FnOnce(MapRef<'doc, Self::Config>) -> R) -> R {
match self {
ReadonlyValue::End(()) => match_fn(MapRef::End(())),
ReadonlyValue::Byte(value) => match_fn(MapRef::Byte(value)),
ReadonlyValue::Short(value) => match_fn(MapRef::Short(value)),
ReadonlyValue::Int(value) => match_fn(MapRef::Int(value)),
ReadonlyValue::Long(value) => match_fn(MapRef::Long(value)),
ReadonlyValue::Float(value) => match_fn(MapRef::Float(value)),
ReadonlyValue::Double(value) => match_fn(MapRef::Double(value)),
ReadonlyValue::ByteArray(value) => match_fn(MapRef::ByteArray(value)),
ReadonlyValue::String(value) => match_fn(MapRef::String(value)),
ReadonlyValue::List(value) => match_fn(MapRef::List(value)),
ReadonlyValue::Compound(value) => match_fn(MapRef::Compound(value)),
ReadonlyValue::IntArray(value) => match_fn(MapRef::IntArray(value)),
ReadonlyValue::LongArray(value) => match_fn(MapRef::LongArray(value)),
}
}
}
impl<'doc, O: ByteOrder, D: Document> From<()> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(_: ()) -> Self {
ReadonlyValue::End(())
}
}
impl<'doc, O: ByteOrder, D: Document> From<i8> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: i8) -> Self {
ReadonlyValue::Byte(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<i16> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: i16) -> Self {
ReadonlyValue::Short(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<i32> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: i32) -> Self {
ReadonlyValue::Int(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<i64> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: i64) -> Self {
ReadonlyValue::Long(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<f32> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: f32) -> Self {
ReadonlyValue::Float(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<f64> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: f64) -> Self {
ReadonlyValue::Double(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<ReadonlyArray<'doc, i8, D>>
for ReadonlyValue<'doc, O, D>
{
#[inline]
fn from(value: ReadonlyArray<'doc, i8, D>) -> Self {
ReadonlyValue::ByteArray(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<ReadonlyString<'doc, D>> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: ReadonlyString<'doc, D>) -> Self {
ReadonlyValue::String(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<ReadonlyList<'doc, O, D>> for ReadonlyValue<'doc, O, D> {
#[inline]
fn from(value: ReadonlyList<'doc, O, D>) -> Self {
ReadonlyValue::List(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<ReadonlyCompound<'doc, O, D>>
for ReadonlyValue<'doc, O, D>
{
#[inline]
fn from(value: ReadonlyCompound<'doc, O, D>) -> Self {
ReadonlyValue::Compound(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<ReadonlyArray<'doc, byteorder::I32<O>, D>>
for ReadonlyValue<'doc, O, D>
{
#[inline]
fn from(value: ReadonlyArray<'doc, byteorder::I32<O>, D>) -> Self {
ReadonlyValue::IntArray(value)
}
}
impl<'doc, O: ByteOrder, D: Document> From<ReadonlyArray<'doc, byteorder::I64<O>, D>>
for ReadonlyValue<'doc, O, D>
{
#[inline]
fn from(value: ReadonlyArray<'doc, byteorder::I64<O>, D>) -> Self {
ReadonlyValue::LongArray(value)
}
}
impl<'doc, O: ByteOrder, D: Document, T: NBT> From<ReadonlyTypedList<'doc, O, D, T>>
for ReadonlyValue<'doc, O, D>
{
#[inline]
fn from(value: ReadonlyTypedList<'doc, O, D, T>) -> Self {
ReadonlyValue::List(ReadonlyList {
data: value.data,
mark: value.mark,
doc: value.doc,
_marker: PhantomData,
})
}
}