Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/data/mod.rs')
-rw-r--r--src/data/mod.rs530
1 files changed, 0 insertions, 530 deletions
diff --git a/src/data/mod.rs b/src/data/mod.rs
deleted file mode 100644
index 0583ea4..0000000
--- a/src/data/mod.rs
+++ /dev/null
@@ -1,530 +0,0 @@
-//! all the IO
-use flate2::{
- Compress, CompressError as CError, Compression, Decompress, DecompressError as DError,
- FlushCompress, FlushDecompress, Status,
-};
-use std::collections::HashMap;
-use std::error::Error;
-use std::fmt;
-use std::str::Utf8Error;
-use thiserror::Error;
-
-pub(crate) mod autotile;
-mod base64;
-pub mod command;
-pub mod dynamic;
-pub mod map;
-pub mod planet;
-pub mod renderer;
-pub mod schematic;
-pub mod sector;
-pub mod weather;
-
-#[derive(Debug)]
-pub struct DataRead<'d> {
- pub(crate) data: &'d [u8],
- // used with read_chunk
- read: usize,
-}
-
-impl fmt::Display for DataRead<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", String::from_utf8_lossy(self.data))
- }
-}
-
-macro_rules! make_read {
- ($name:ident, $type:ty) => {
- pub fn $name(&mut self) -> Result<$type, ReadError> {
- const LEN: usize = std::mem::size_of::<$type>();
- if self.data.len() < LEN {
- return Err(ReadError::Underflow {
- need: LEN,
- have: self.data.len(),
- });
- }
- let mut output = [0u8; LEN];
- output.copy_from_slice(&self.data[..LEN]);
- self.data = &self.data[LEN..];
- self.read += LEN;
- Ok(<$type>::from_be_bytes(output))
- }
- };
-}
-
-impl<'d> DataRead<'d> {
- #[must_use]
- pub const fn new(data: &'d [u8]) -> Self {
- Self { data, read: 0 }
- }
-
- pub fn read_bool(&mut self) -> Result<bool, ReadError> {
- Ok(self.read_u8()? != 0)
- }
-
- make_read!(read_u8, u8);
- make_read!(read_i8, i8);
- make_read!(read_u16, u16);
- make_read!(read_i16, i16);
- make_read!(read_u32, u32);
- make_read!(read_i32, i32);
- make_read!(read_f32, f32);
- make_read!(read_u64, u64);
- make_read!(read_i64, i64);
- make_read!(read_f64, f64);
-
- pub fn read_utf(&mut self) -> Result<&'d str, ReadError> {
- if self.data.len() < 2 {
- return Err(ReadError::Underflow {
- need: 2,
- have: self.data.len(),
- });
- }
- let len = self.read_u16()?;
- let end = len as usize;
- if self.data.len() < end {
- return Err(ReadError::Underflow {
- need: end,
- have: self.data.len(),
- });
- }
- let result = std::str::from_utf8(&self.data[..end])?;
- self.data = &self.data[end..];
- self.read += end;
- Ok(result)
- }
-
- pub fn read_bytes(&mut self, dst: &mut [u8]) -> Result<(), ReadError> {
- if self.data.len() < dst.len() {
- return Err(ReadError::Underflow {
- need: dst.len(),
- have: self.data.len(),
- });
- }
- dst.copy_from_slice(&self.data[..dst.len()]);
- self.data = &self.data[dst.len()..];
- self.read += dst.len();
- Ok(())
- }
-
- pub fn skip(&mut self, n: usize) -> Result<(), ReadError> {
- if self.data.len() < n {
- return Err(ReadError::Underflow {
- need: n,
- have: self.data.len(),
- });
- }
- self.data = &self.data[n..];
- self.read += n;
- Ok(())
- }
-
- pub fn skip_chunk(&mut self) -> Result<usize, ReadError> {
- let len = self.read_u32()? as usize;
- self.skip(len)?;
- Ok(len)
- }
-
- pub fn read_chunk<E>(
- &mut self,
- big: bool,
- f: impl FnOnce(&mut DataRead) -> Result<(), E>,
- ) -> Result<(), E>
- where
- E: Error + From<ReadError>,
- {
- let len = if big {
- self.read_u32()? as usize
- } else {
- self.read_u16()? as usize
- };
- self.read = 0;
- let r = f(self);
- match r {
- Err(e) => {
- // skip this chunk
- assert!(
- len >= self.read,
- "overread; supposed to read {len}; read {}",
- self.read
- );
- let n = len - self.read;
- if n != 0 {
- #[cfg(debug_assertions)]
- println!(
- "supposed to read {len}; read {} - skipping excess",
- self.read
- );
- self.skip(n)?;
- };
- Err(e)
- }
- Ok(_) => Ok(()),
- }
- }
-
- pub fn read_vec(&mut self, dst: &mut Vec<u8>, len: usize) -> Result<(), ReadError> {
- if self.data.len() < len {
- return Err(ReadError::Underflow {
- need: len,
- have: self.data.len(),
- });
- }
- dst.extend_from_slice(&self.data[..len]);
- self.data = &self.data[len..];
- self.read += len;
- Ok(())
- }
-
- pub fn read_map(&mut self, dst: &mut HashMap<String, String>) -> Result<(), ReadError> {
- let n = self.read_u8()?;
- for _ in 0..n {
- let key = self.read_utf()?;
- let value = self.read_utf()?;
- dst.insert(key.to_owned(), value.to_owned());
- }
- Ok(())
- }
-
- pub fn deflate(&mut self) -> Result<Vec<u8>, DecompressError> {
- let mut dec = Decompress::new(true);
- let mut raw = Vec::<u8>::new();
- raw.reserve(1024);
- loop {
- let t_in = dec.total_in();
- let t_out = dec.total_out();
- let res = dec.decompress_vec(self.data, &mut raw, FlushDecompress::Finish)?;
- if dec.total_in() > t_in {
- // we have to advance input every time, decompress_vec only knows the output position
- self.data = &self.data[(dec.total_in() - t_in) as usize..];
- }
- match res {
- // there's no more input (and the flush mode says so), we need to reserve additional space
- Status::Ok | Status::BufError => (),
- // input was already at the end, so this is referring to the output
- Status::StreamEnd => break,
- }
- if dec.total_in() == t_in && dec.total_out() == t_out {
- // protect against looping forever
- return Err(DecompressError::DecompressStall);
- }
- raw.reserve(1024);
- }
- assert_eq!(dec.total_out() as usize, raw.len());
- self.read = 0;
- Ok(raw)
- }
-}
-
-#[derive(Debug, Error)]
-pub enum DecompressError {
- #[error("zlib decompression failed")]
- Decompress(#[from] DError),
- #[error("decompressor stalled before completion")]
- DecompressStall,
-}
-
-#[derive(Debug, Error)]
-pub enum ReadError {
- #[error("buffer underflow (expected {need} but got {have})")]
- Underflow { need: usize, have: usize },
- #[error("expected {0}")]
- Expected(&'static str),
- #[error("malformed utf8 in string")]
- Utf8 {
- #[from]
- source: Utf8Error,
- },
-}
-
-impl PartialEq for ReadError {
- fn eq(&self, _: &Self) -> bool {
- false
- }
-}
-
-enum WriteBuff<'d> {
- // unlike the DataRead want to access the written region after
- Ref { raw: &'d mut [u8], pos: usize },
- Vec(Vec<u8>),
-}
-
-impl<'d> WriteBuff<'d> {
- fn check_capacity(&self, need: usize) -> Result<(), WriteError> {
- match self {
- Self::Ref { raw, pos } if raw.len() - pos < need => Err(WriteError::Overflow {
- need,
- have: raw.len() - pos,
- }),
- _ => Ok(()),
- }
- }
-
- fn write(&mut self, data: &[u8]) {
- match self {
- Self::Ref { raw, pos } => {
- let end = *pos + data.len();
- raw[*pos..end].copy_from_slice(data);
- *pos += data.len();
- }
- Self::Vec(v) => v.extend_from_slice(data),
- }
- }
-}
-
-pub struct DataWrite<'d> {
- data: WriteBuff<'d>,
-}
-
-macro_rules! make_write {
- ($name:ident, $type:ty) => {
- pub fn $name(&mut self, val: $type) -> Result<(), WriteError> {
- const LEN: usize = std::mem::size_of::<$type>();
- self.data.check_capacity(LEN)?;
- self.data.write(&<$type>::to_be_bytes(val));
- Ok(())
- }
- };
-}
-
-impl<'d> DataWrite<'d> {
- pub fn write_bool(&mut self, val: bool) -> Result<(), WriteError> {
- self.write_u8(u8::from(val))
- }
-
- make_write!(write_u8, u8);
- make_write!(write_i8, i8);
- make_write!(write_u16, u16);
- make_write!(write_i16, i16);
- make_write!(write_u32, u32);
- make_write!(write_i32, i32);
- make_write!(write_f32, f32);
- make_write!(write_u64, u64);
- make_write!(write_i64, i64);
- make_write!(write_f64, f64);
-
- pub fn write_utf(&mut self, val: &str) -> Result<(), WriteError> {
- if val.len() > u16::MAX as usize {
- return Err(WriteError::TooLong { len: val.len() });
- }
- self.data.check_capacity(2 + val.len())?;
- self.data.write(&u16::to_be_bytes(val.len() as u16));
- self.data.write(val.as_bytes());
- Ok(())
- }
-
- pub fn write_bytes(&mut self, val: &[u8]) -> Result<(), WriteError> {
- self.data.check_capacity(val.len())?;
- self.data.write(val);
- Ok(())
- }
-
- #[must_use]
- pub const fn is_owned(&self) -> bool {
- matches!(self.data, WriteBuff::Vec(..))
- }
-
- #[must_use]
- pub fn get_written(&self) -> &[u8] {
- match &self.data {
- WriteBuff::Ref { raw, pos } => &raw[..*pos],
- WriteBuff::Vec(v) => v,
- }
- }
-
- /// eat this datawrite
- ///
- /// panics if ref write buffer
- #[must_use]
- pub fn consume(self) -> Vec<u8> {
- match self.data {
- WriteBuff::Vec(v) => v,
- WriteBuff::Ref { .. } => unreachable!(),
- }
- }
-
- pub fn inflate(self, to: &mut DataWrite) -> Result<(), CompressError> {
- // compress into the provided buffer
- let WriteBuff::Vec(raw) = self.data else {
- unreachable!("write buffer not owned")
- };
- let mut comp = Compress::new(Compression::default(), true);
- // compress the immediate buffer into a temp buffer to copy it to buff? no thanks
- match to.data {
- WriteBuff::Ref {
- raw: ref mut dst,
- ref mut pos,
- } => {
- match comp.compress(&raw, &mut dst[*pos..], FlushCompress::Finish)? {
- // there's no more input (and the flush mode says so), but we can't resize the output
- Status::Ok | Status::BufError => {
- return Err(CompressError::CompressEof(
- raw.len() - comp.total_in() as usize,
- ))
- }
- Status::StreamEnd => (),
- }
- }
- WriteBuff::Vec(ref mut dst) => {
- let mut input = raw.as_ref();
- dst.reserve(1024);
- loop {
- let t_in = comp.total_in();
- let t_out = comp.total_out();
- let res = comp.compress_vec(input, dst, FlushCompress::Finish)?;
- if comp.total_in() > t_in {
- // we have to advance input every time, compress_vec only knows the output position
- input = &input[(comp.total_in() - t_in) as usize..];
- }
- match res {
- // there's no more input (and the flush mode says so), we need to reserve additional space
- Status::Ok | Status::BufError => (),
- // input was already at the end, so this is referring to the output
- Status::StreamEnd => break,
- }
- if comp.total_in() == t_in && comp.total_out() == t_out {
- // protect against looping forever
- return Err(CompressError::CompressStall);
- }
- dst.reserve(1024);
- }
- }
- }
- assert_eq!(comp.total_in() as usize, raw.len());
- Ok(())
- }
-}
-
-impl Default for DataWrite<'static> {
- fn default() -> Self {
- Self {
- data: WriteBuff::Vec(Vec::new()),
- }
- }
-}
-
-#[derive(Debug, Error)]
-pub enum CompressError {
- #[error(transparent)]
- Compress(#[from] CError),
- #[error("compression overflow with {0} bytes of input remaining")]
- CompressEof(usize),
- #[error("compressor stalled before completion")]
- CompressStall,
-}
-
-#[derive(Debug, Error)]
-pub enum WriteError {
- #[error("buffer overflow (expected {need} but got {have})")]
- Overflow { need: usize, have: usize },
- #[error("string too long ({len} bytes of {})", u16::MAX)]
- TooLong { len: usize },
-}
-
-impl PartialEq for WriteError {
- fn eq(&self, _: &Self) -> bool {
- false
- }
-}
-
-impl<'d> From<&'d mut [u8]> for DataWrite<'d> {
- fn from(value: &'d mut [u8]) -> Self {
- Self {
- data: WriteBuff::Ref { raw: value, pos: 0 },
- }
- }
-}
-
-impl From<Vec<u8>> for DataWrite<'static> {
- fn from(value: Vec<u8>) -> Self {
- Self {
- data: WriteBuff::Vec(value),
- }
- }
-}
-
-impl<'d> TryFrom<DataWrite<'d>> for Vec<u8> {
- type Error = ();
-
- fn try_from(value: DataWrite<'d>) -> Result<Self, Self::Error> {
- match value.data {
- WriteBuff::Vec(v) => Ok(v),
- WriteBuff::Ref { .. } => Err(()),
- }
- }
-}
-/// basic serialization/deserialization functions
-pub trait Serializer<D> {
- type ReadError;
- type WriteError;
-
- fn deserialize(&mut self, buff: &mut DataRead<'_>) -> Result<D, Self::ReadError>;
-
- fn serialize(&mut self, buff: &mut DataWrite<'_>, data: &D) -> Result<(), Self::WriteError>;
-}
-
-#[derive(Clone, Copy, Eq, PartialEq)]
-pub struct GridPos(pub usize, pub usize);
-
-impl From<u32> for GridPos {
- fn from(value: u32) -> Self {
- GridPos((value >> 16) as u16 as usize, value as u16 as usize)
- }
-}
-
-impl From<GridPos> for u32 {
- /// ```
- /// # use mindus::data::GridPos;
- /// assert_eq!(GridPos::from(u32::from(GridPos(1000, 5))), GridPos(1000, 5));
- /// ```
- fn from(value: GridPos) -> Self {
- ((value.0 << 16) | value.1) as u32
- }
-}
-
-impl fmt::Debug for GridPos {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "({0}, {1})", self.0, self.1)
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn read() {
- let mut read = DataRead::new("Thé qûick ઉrown fox 🦘 over\0\rthe lazy dog.".as_bytes());
- assert_eq!(read.read_u8(), Ok(84));
- assert_eq!(read.read_i8(), Ok(104));
- assert_eq!(read.read_i8(), Ok(-61));
- assert_eq!(read.read_u16(), Ok(43296));
- assert_eq!(read.read_i16(), Ok(29123));
- assert_eq!(read.read_i16(), Ok(-17559));
- assert_eq!(read.read_i32(), Ok(1_667_965_152));
- assert_eq!(read.read_i32(), Ok(-1_433_832_849));
- assert_eq!(read.read_i64(), Ok(8_605_851_562_280_493_296));
- assert_eq!(read.read_i64(), Ok(-6_942_694_510_468_635_278));
- assert_eq!(read.read_utf(), Ok("the lazy dog."));
- }
-
- #[test]
- fn write() {
- let mut write = DataWrite::default();
- assert_eq!(write.write_u8(84), Ok(()));
- assert_eq!(write.write_i8(104), Ok(()));
- assert_eq!(write.write_i8(-61), Ok(()));
- assert_eq!(write.write_u16(43296), Ok(()));
- assert_eq!(write.write_i16(29123), Ok(()));
- assert_eq!(write.write_i16(-17559), Ok(()));
- assert_eq!(write.write_i32(1_667_965_152), Ok(()));
- assert_eq!(write.write_i32(-1_433_832_849), Ok(()));
- assert_eq!(write.write_i64(8_605_851_562_280_493_296), Ok(()));
- assert_eq!(write.write_i64(-6_942_694_510_468_635_278), Ok(()));
- assert_eq!(write.write_utf("the lazy dog."), Ok(()));
- assert_eq!(
- write.get_written(),
- "Thé qûick ઉrown fox 🦘 over\0\rthe lazy dog.".as_bytes()
- );
- }
-}