use crate::ClientError;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use core::marker::PhantomData;
use rseip_core::{codec::*, Error};
use smallvec::SmallVec;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type BOOL = bool;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type DWORD = u32;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type SINT = i8;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type INT = i16;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type DINT = i32;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type LINT = i64;
#[allow(clippy::upper_case_acronyms)]
#[allow(unused)]
pub type REAL = f32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TagType {
Bool,
Dword,
Sint,
Int,
Dint,
Lint,
Real,
Structure(u16),
}
impl TagType {
#[inline]
pub fn type_code(&self) -> u16 {
match self {
Self::Bool => 0xC1,
Self::Dword => 0xD3,
Self::Sint => 0xC2,
Self::Int => 0xC3,
Self::Dint => 0xC4,
Self::Lint => 0xC5,
Self::Real => 0xCA,
Self::Structure { .. } => 0x02A0,
}
}
pub fn is_structure(&self) -> bool {
match self {
Self::Structure(_) => true,
_ => false,
}
}
pub fn is_atomic(&self) -> bool {
!self.is_structure()
}
pub fn structure_handle(&self) -> Option<u16> {
match self {
Self::Structure(v) => Some(*v),
_ => None,
}
}
}
impl Encode for TagType {
#[inline]
fn encode_by_ref<A: Encoder>(
&self,
buf: &mut BytesMut,
encoder: &mut A,
) -> Result<(), A::Error> {
match self {
Self::Bool => {
encoder.encode_u16(0xC1, buf)?;
}
Self::Sint => {
encoder.encode_u16(0xC2, buf)?;
}
Self::Int => {
encoder.encode_u16(0xC3, buf)?;
}
Self::Dint => {
encoder.encode_u16(0xC4, buf)?;
}
Self::Real => {
encoder.encode_u16(0xCA, buf)?;
}
Self::Dword => {
encoder.encode_u16(0xD3, buf)?;
}
Self::Lint => {
encoder.encode_u16(0xC5, buf)?;
}
Self::Structure(handle) => {
encoder.encode(&[0xA0, 0x02], buf)?;
encoder.encode_u16(*handle, buf)?;
}
}
Ok(())
}
#[inline(always)]
fn bytes_count(&self) -> usize {
match self {
Self::Structure(_) => 4,
_ => 2,
}
}
}
impl<'de> Decode<'de> for TagType {
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
decoder.ensure_size(3)?;
let type_code = decoder.decode_u16();
let val = match type_code {
0xC2 => TagType::Sint,
0xC3 => TagType::Int,
0xC4 => TagType::Dint,
0xCA => TagType::Real,
0xD3 => TagType::Dword,
0xC5 => TagType::Lint,
0xC1 => TagType::Bool,
0x02A0 => {
decoder.ensure_size(2)?;
TagType::Structure(decoder.decode_u16())
}
_ => {
return Err(Error::custom(format!(
"unexpected type code: {}",
type_code
)))
}
};
Ok(val)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TagValue<V> {
pub tag_type: TagType,
pub value: V,
}
macro_rules! impl_atomic {
($ty:ty, $size: tt) => {
impl<'de> Decode<'de> for TagValue<$ty> {
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let tag_type = decoder.decode_any()?;
let value = decoder.decode_any()?;
Ok(Self { tag_type, value })
}
}
impl Encode for TagValue<$ty> {
#[inline]
fn encode<A: Encoder>(
self,
buf: &mut BytesMut,
encoder: &mut A,
) -> Result<(), A::Error> {
self.tag_type.encode(buf, encoder)?;
buf.put_slice(&[1, 0]);
self.value.encode(buf, encoder)?;
Ok(())
}
#[inline]
fn encode_by_ref<A: Encoder>(
&self,
buf: &mut BytesMut,
encoder: &mut A,
) -> Result<(), A::Error> {
self.tag_type.encode(buf, encoder)?;
buf.put_slice(&[1, 0]);
self.value.encode_by_ref(buf, encoder)?;
Ok(())
}
#[inline]
fn bytes_count(&self) -> usize {
self.tag_type.bytes_count() + 2 + $size
}
}
};
}
impl_atomic!(bool, 1);
impl_atomic!(i8, 1);
impl_atomic!(u8, 1);
impl_atomic!(i16, 2);
impl_atomic!(u16, 2);
impl_atomic!(i32, 4);
impl_atomic!(u32, 4);
impl_atomic!(i64, 8);
impl_atomic!(u64, 8);
impl_atomic!(f32, 4);
impl_atomic!(f64, 8);
macro_rules! impl_seq {
($ty:tt) => {
impl<T> Encode for TagValue<$ty<T>>
where
T: Encode,
{
#[inline]
fn encode<A: Encoder>(self, buf: &mut BytesMut, encoder: &mut A) -> Result<(), A::Error>
where
Self: Sized,
{
self.tag_type.encode(buf, encoder)?;
encoder.encode_u16(self.value.len() as u16, buf)?;
self.value.encode(buf, encoder)?;
Ok(())
}
#[inline]
fn encode_by_ref<A: Encoder>(
&self,
buf: &mut BytesMut,
encoder: &mut A,
) -> Result<(), A::Error> {
self.tag_type.encode(buf, encoder)?;
encoder.encode_u16(self.value.len() as u16, buf)?;
self.value.encode_by_ref(buf, encoder)?;
Ok(())
}
#[inline]
fn bytes_count(&self) -> usize {
self.tag_type.bytes_count() + 2 + self.value.bytes_count()
}
}
};
}
impl_seq!(Vec);
impl<T, const N: usize> Encode for TagValue<[T; N]>
where
T: Encode,
{
#[inline]
fn encode<A: Encoder>(self, buf: &mut BytesMut, encoder: &mut A) -> Result<(), A::Error>
where
Self: Sized,
{
self.tag_type.encode(buf, encoder)?;
encoder.encode_u16(self.value.len() as u16, buf)?;
self.value.encode(buf, encoder)?;
Ok(())
}
#[inline]
fn encode_by_ref<A: Encoder>(
&self,
buf: &mut BytesMut,
encoder: &mut A,
) -> Result<(), A::Error> {
self.tag_type.encode(buf, encoder)?;
encoder.encode_u16(self.value.len() as u16, buf)?;
self.value.encode_by_ref(buf, encoder)?;
Ok(())
}
#[inline]
fn bytes_count(&self) -> usize {
self.tag_type.bytes_count() + 2 + self.value.bytes_count()
}
}
impl<T> Encode for TagValue<&[T]>
where
T: Encode,
{
#[inline]
fn encode_by_ref<A: Encoder>(
&self,
buf: &mut BytesMut,
encoder: &mut A,
) -> Result<(), A::Error> {
self.tag_type.encode(buf, encoder)?;
encoder.encode_u16(self.value.len() as u16, buf)?;
for item in self.value.iter() {
item.encode_by_ref(buf, encoder)?;
}
Ok(())
}
#[inline]
fn bytes_count(&self) -> usize {
self.tag_type.bytes_count() + 2 + self.value.iter().map(|v| v.bytes_count()).sum::<usize>()
}
}
impl<'de> Decode<'de> for TagValue<Bytes> {
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let tag_type: TagType = decoder.decode_any()?;
let data: BytesHolder = decoder.decode_any()?;
Ok(Self {
tag_type,
value: data.into(),
})
}
}
impl<'de, T> Decode<'de> for TagValue<Vec<T>>
where
T: Decode<'de>,
{
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let tag_type: TagType = decoder.decode_any()?;
let mut data = Vec::new();
while decoder.buf().has_remaining() {
let v: T = decoder.decode_any()?;
data.push(v);
}
Ok(Self {
tag_type,
value: data,
})
}
}
impl<'de, T> Decode<'de> for TagValue<SmallVec<T>>
where
T: smallvec::Array,
T::Item: Decode<'de>,
{
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let tag_type: TagType = decoder.decode_any()?;
let mut data = SmallVec::new();
while decoder.buf().has_remaining() {
let v: T::Item = decoder.decode_any()?;
data.push(v);
}
Ok(Self {
tag_type,
value: data,
})
}
}
#[derive(Debug)]
pub struct TagValueTypedIter<T> {
tag_type: TagType,
decoder: LittleEndianDecoder<ClientError>,
_marker: PhantomData<T>,
}
impl<T> TagValueTypedIter<T> {
#[allow(unused)]
pub fn tag_type(&self) -> TagType {
self.tag_type
}
pub fn from_bytes(buf: Bytes) -> Result<Self, ClientError> {
let mut decoder = LittleEndianDecoder::new(buf);
let tag_type = decoder.decode_any()?;
Ok(Self {
tag_type,
decoder,
_marker: Default::default(),
})
}
}
impl<'de, T> Iterator for TagValueTypedIter<T>
where
T: Decode<'de>,
{
type Item = Result<T, ClientError>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.decoder.has_remaining() {
Some(self.decoder.decode_any())
} else {
None
}
}
}
impl<'de, T> Decode<'de> for TagValueTypedIter<T> {
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let tag_type: TagType = decoder.decode_any()?;
let len = decoder.buf_mut().remaining();
let buf = decoder.buf_mut().copy_to_bytes(len);
let res = Self {
tag_type,
decoder: LittleEndianDecoder::new(buf),
_marker: Default::default(),
};
Ok(res)
}
}
#[derive(Debug)]
pub struct TagValueIter {
tag_type: TagType,
decoder: LittleEndianDecoder<ClientError>,
}
impl TagValueIter {
#[allow(unused)]
pub fn tag_type(&self) -> TagType {
self.tag_type
}
pub fn from_bytes(buf: Bytes) -> Result<Self, ClientError> {
let mut decoder = LittleEndianDecoder::new(buf);
let tag_type = decoder.decode_any()?;
Ok(Self { tag_type, decoder })
}
}
impl TagValueIter {
#[inline]
pub fn next<'de, T>(&mut self) -> Option<Result<T, ClientError>>
where
T: Decode<'de>,
{
if self.decoder.has_remaining() {
Some(self.decoder.decode_any())
} else {
None
}
}
}
impl<'de> Decode<'de> for TagValueIter {
#[inline]
fn decode<D>(mut decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let tag_type: TagType = decoder.decode_any()?;
let len = decoder.buf_mut().remaining();
let buf = decoder.buf_mut().copy_to_bytes(len);
let res = Self {
tag_type,
decoder: LittleEndianDecoder::new(buf),
};
Ok(res)
}
}