use std::{borrow::Cow, fmt};
use byteorder::{BigEndian, ReadBytesExt};
use serde::Deserialize;
use crate::{CompTag, BYTE_ARRAY_TAG, INT_ARRAY_TAG, LONG_ARRAY_TAG};
#[derive(Deserialize, Debug, Clone, Copy)]
pub struct ByteArray<'a> {
tag: CompTag<BYTE_ARRAY_TAG>,
data: &'a [u8],
}
impl<'a> ByteArray<'a> {
pub fn iter(&self) -> ByteIter<'a> {
ByteIter(*self)
}
}
pub struct ByteIter<'a>(ByteArray<'a>);
impl<'a> Iterator for ByteIter<'a> {
type Item = i8;
fn next(&mut self) -> Option<Self::Item> {
self.0.data.read_i8().ok()
}
}
#[derive(Deserialize, Debug, Clone, Copy)]
pub struct IntArray<'a> {
tag: CompTag<INT_ARRAY_TAG>,
data: &'a [u8],
}
impl<'a> IntArray<'a> {
pub fn iter(&self) -> IntIter<'a> {
IntIter(*self)
}
}
pub struct IntIter<'a>(IntArray<'a>);
impl<'a> Iterator for IntIter<'a> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
self.0.data.read_i32::<BigEndian>().ok()
}
}
#[derive(Deserialize, Debug, Clone, Copy)]
pub struct LongArray<'a> {
tag: CompTag<LONG_ARRAY_TAG>,
data: &'a [u8],
}
impl<'a> LongArray<'a> {
pub fn iter(&self) -> LongIter<'a> {
LongIter(*self)
}
}
pub struct LongIter<'a>(LongArray<'a>);
impl<'a> Iterator for LongIter<'a> {
type Item = i64;
fn next(&mut self) -> Option<Self::Item> {
self.0.data.read_i64::<BigEndian>().ok()
}
}
struct CowStr<'a>(Cow<'a, str>);
impl<'de> serde::Deserialize<'de> for CowStr<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(CowStrVisitor)
}
}
struct CowStrVisitor;
impl<'de> serde::de::Visitor<'de> for CowStrVisitor {
type Value = CowStr<'de>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(CowStr(Cow::Borrowed(value)))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(CowStr(Cow::Owned(value.to_owned())))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(CowStr(Cow::Owned(value)))
}
}
pub fn deserialize_cow_str<'de, D>(deserializer: D) -> Result<Cow<'de, str>, D::Error>
where
D: serde::Deserializer<'de>,
{
let wrapper = CowStr::deserialize(deserializer)?;
Ok(wrapper.0)
}