82 lines
2.1 KiB
Rust
82 lines
2.1 KiB
Rust
use std::io::{Error, ErrorKind, Read, Write};
|
|
|
|
use pumpkin_macros::packet;
|
|
|
|
const MAX_ACK_RECORDS: u16 = 4096;
|
|
|
|
use crate::{
|
|
codec::u24,
|
|
serial::{PacketRead, PacketWrite},
|
|
};
|
|
|
|
#[packet(0xC0)]
|
|
pub struct Ack {
|
|
sequences: Vec<u32>,
|
|
}
|
|
|
|
impl Ack {
|
|
#[must_use]
|
|
pub const fn new(sequences: Vec<u32>) -> Self {
|
|
Self { sequences }
|
|
}
|
|
|
|
fn write_range<W: Write>(start: u32, end: u32, writer: &mut W) -> Result<(), Error> {
|
|
if start == end {
|
|
1u8.write(writer)?;
|
|
u24(start).write(writer)
|
|
} else {
|
|
0u8.write(writer)?;
|
|
u24(start).write(writer)?;
|
|
u24(end).write(writer)
|
|
}
|
|
}
|
|
|
|
pub fn read<R: Read>(reader: &mut R) -> Result<Self, Error> {
|
|
let size = u16::read_be(reader)?;
|
|
|
|
if size > MAX_ACK_RECORDS {
|
|
return Err(Error::new(
|
|
ErrorKind::InvalidData,
|
|
"ACK packet range is too large.",
|
|
));
|
|
}
|
|
|
|
let mut sequences = Vec::with_capacity(size as usize);
|
|
for _ in 0..size {
|
|
let single = bool::read(reader)?;
|
|
if single {
|
|
sequences.push(u24::read(reader)?.0);
|
|
} else {
|
|
let start = u24::read(reader)?.0;
|
|
let end = u24::read(reader)?.0;
|
|
for i in start..end {
|
|
sequences.push(i);
|
|
}
|
|
}
|
|
}
|
|
Ok(Self { sequences })
|
|
}
|
|
|
|
pub fn write<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
|
0xC0u8.write(writer)?;
|
|
let mut count: u16 = 0;
|
|
|
|
let mut buf = Vec::new();
|
|
|
|
let mut start = self.sequences[0];
|
|
let mut end = start;
|
|
for seq in self.sequences.iter().copied() {
|
|
if seq != end + 1 {
|
|
Self::write_range(start, end, &mut buf)?;
|
|
count += 1;
|
|
start = seq;
|
|
}
|
|
end = seq;
|
|
}
|
|
Self::write_range(start, end, &mut buf)?;
|
|
count += 1;
|
|
count.write_be(writer)?;
|
|
writer.write_all(&buf)
|
|
}
|
|
}
|