1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use serde::de::DeserializeOwned;
use serde::Serialize;
use crate::packet::{CustomError, InputPacketBytes, InputPacketBytesResult, OutputPacketBytes, PacketReadable, PacketReadableResult, PacketWritable, PacketWritableResult};
use crate::types::{ReadProtocolNbt, WriteProtocolNbt, WriteRemainingBytesArray};

#[async_trait::async_trait]
impl<'a, T: Serialize + Sync + Send> PacketWritable for WriteProtocolNbt<'a, T> {
    async fn write(&self, output: &mut impl OutputPacketBytes) -> PacketWritableResult {
        WriteRemainingBytesArray::from(
            &fastnbt::to_bytes(self.value)
                .map_err(|err| CustomError::Error(Box::new(err)))?
        )
            .write(output).await
    }
}

struct MemorizeInputPacketBytes<'a, T: InputPacketBytes> {
    pub bytes: Vec<u8>,
    pub input: &'a mut T,
}

impl<'a, T: InputPacketBytes> MemorizeInputPacketBytes<'a, T> {
    async fn skip_bytes(&mut self, size: usize) -> InputPacketBytesResult<()> {
        let mut vec = Vec::with_capacity(size);
        unsafe { vec.set_len(size); }
        self.take_vec(&mut vec, size).await
    }
}

#[async_trait::async_trait]
impl<'a, T: InputPacketBytes> InputPacketBytes for MemorizeInputPacketBytes<'a, T> {
    async fn take_byte(&mut self) -> InputPacketBytesResult<u8> {
        let byte = self.input.take_byte().await?;
        self.bytes.push(byte);
        Ok(byte)
    }

    async fn take_slice(&mut self, slice: &mut [u8]) -> InputPacketBytesResult<()> {
        self.input.take_slice(slice).await?;
        self.bytes.extend_from_slice(slice);
        Ok(())
    }

    async fn take_vec(&mut self, vec: &mut Vec<u8>, count: usize) -> InputPacketBytesResult<()> {
        self.input.take_vec(vec, count).await?;
        self.bytes.extend_from_slice(vec.as_slice());
        Ok(())
    }

    fn has_bytes(&self, count: usize) -> bool {
        self.input.has_bytes(count)
    }

    fn remaining_bytes(&self) -> usize {
        self.input.remaining_bytes()
    }
}

async fn read_nbt(input: &mut impl InputPacketBytes) -> PacketReadableResult<Vec<u8>> {
    let mut memorize = MemorizeInputPacketBytes { input, bytes: Vec::new() };
    let tag = u8::read(&mut memorize).await?;
    if tag != 0 {
        let length = u16::read(&mut memorize).await?;
        memorize.skip_bytes(length as usize).await?;
        skip_tag(tag, 1, &mut memorize).await?
    }
    Ok(memorize.bytes)
}

#[async_recursion::async_recursion]
async fn skip_tag<I: InputPacketBytes>(
    tag: u8, count: usize, input: &mut MemorizeInputPacketBytes<'_, I>,
) -> PacketReadableResult<()> {
    Ok(match tag {
        0 => (),
        1 => input.skip_bytes(count).await?,
        2 => input.skip_bytes(count * 2).await?,
        3 | 5 => input.skip_bytes(count * 4).await?,
        4 | 6 => input.skip_bytes(count * 8).await?,
        7 => {
            let length = i32::read(input).await?;
            if length <= 0 { return Ok(()); }
            input.skip_bytes(length as usize).await?
        }
        8 => {
            let length = u16::read(input).await?;
            input.skip_bytes(length as usize).await?
        }
        9 => {
            let tag = u8::read(input).await?;
            let size = i32::read(input).await?;
            if size <= 0 { return Ok(()); }
            skip_tag(tag, size as usize, input).await?
        }
        10 => loop {
            let tag = u8::read(input).await?;
            if tag == 0 { break (); }
            let name_length = u16::read(input).await?;
            input.skip_bytes(name_length as usize).await?;
            skip_tag(tag, 1, input).await?
        }
        11 => {
            let length = i32::read(input).await?;
            if length <= 0 { return Ok(()); }
            input.skip_bytes(length as usize * 4).await?
        }
        12 => {
            let length = i32::read(input).await?;
            if length <= 0 { return Ok(()); }
            input.skip_bytes(length as usize * 8).await?
        }
        _ => Err(CustomError::StaticStr("Bad nbt tag value"))?
    })
}

#[async_trait::async_trait]
impl<T: DeserializeOwned + Send + Sync> PacketReadable for ReadProtocolNbt<T> {
    async fn read(input: &mut impl InputPacketBytes) -> PacketReadableResult<Self> {
        let bytes = read_nbt(input).await?;
        Ok(ReadProtocolNbt {
            value: fastnbt::from_bytes(bytes.as_slice())
                .map_err(|err| CustomError::Error(Box::new(err)))?
        })
    }
}