mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/block/logic.rs')
-rw-r--r--src/block/logic.rs209
1 files changed, 26 insertions, 183 deletions
diff --git a/src/block/logic.rs b/src/block/logic.rs
index 24c7b2c..79941c4 100644
--- a/src/block/logic.rs
+++ b/src/block/logic.rs
@@ -1,18 +1,11 @@
//! logic processors and stuff
use std::borrow::Cow;
-use std::error::Error;
-use std::fmt;
use std::string::FromUtf8Error;
-use flate2::{
- Compress, CompressError, Compression, Decompress, DecompressError, FlushCompress,
- FlushDecompress, Status,
-};
-
use crate::block::simple::*;
use crate::block::*;
use crate::data::dynamic::DynType;
-use crate::data::{self, DataRead, DataWrite};
+use crate::data::{self, CompressError, DataRead, DataWrite};
make_simple!(LogicBlock);
@@ -167,37 +160,9 @@ impl BlockLogic for ProcessorLogic {
match data {
DynData::Empty => Ok(Some(Self::create_state(ProcessorState::default()))),
DynData::ByteArray(arr) => {
- let mut input = arr.as_ref();
- 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 = ProcessorDeserializeError::forward(dec.decompress_vec(
- input,
- &mut raw,
- FlushDecompress::Finish,
- ))?;
- if dec.total_in() > t_in {
- // we have to advance input every time, decompress_vec only knows the output position
- input = &input[(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(DeserializeError::Custom(Box::new(
- ProcessorDeserializeError::DecompressStall,
- )));
- }
- raw.reserve(1024);
- }
- let mut buff = DataRead::new(&raw);
+ let input = arr.as_ref();
+ let buff = DataRead::new(input).deflate()?;
+ let mut buff = DataRead::new(&buff);
let ver = ProcessorDeserializeError::forward(buff.read_u8())?;
if ver != 1 {
return Err(DeserializeError::Custom(Box::new(
@@ -279,48 +244,23 @@ impl BlockLogic for ProcessorLogic {
ProcessorSerializeError::forward(rbuff.write_i16(link.x))?;
ProcessorSerializeError::forward(rbuff.write_i16(link.y))?;
}
- let mut input = rbuff.get_written();
- let mut comp = Compress::new(Compression::default(), true);
- let mut dst = Vec::<u8>::new();
- dst.reserve(1024);
- loop {
- let t_in = comp.total_in();
- let t_out = comp.total_out();
- let res = ProcessorSerializeError::forward(comp.compress_vec(
- input,
- &mut 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(SerializeError::Custom(Box::new(
- ProcessorSerializeError::CompressStall,
- )));
- }
- dst.reserve(1024);
- }
- Ok(DynData::ByteArray(dst))
+ let mut out = DataWrite::default();
+ rbuff.inflate(&mut out)?;
+ Ok(DynData::ByteArray(out.consume()))
}
}
-#[derive(Debug)]
+#[derive(Debug, thiserror::Error)]
pub enum ProcessorDeserializeError {
- Read(data::ReadError),
- Decompress(DecompressError),
- DecompressStall,
- FromUtf8(FromUtf8Error),
+ #[error("failed to read state data")]
+ Read(#[from] data::ReadError),
+ #[error("malformed utf-8 in processor code")]
+ FromUtf8(#[from] FromUtf8Error),
+ #[error("unsupported version ({0})")]
Version(u8),
+ #[error("invalid code length ({0})")]
CodeLength(i32),
+ #[error("invalid link count {0}")]
LinkCount(i32),
}
@@ -333,54 +273,12 @@ impl ProcessorDeserializeError {
}
}
-impl From<data::ReadError> for ProcessorDeserializeError {
- fn from(value: data::ReadError) -> Self {
- Self::Read(value)
- }
-}
-
-impl From<DecompressError> for ProcessorDeserializeError {
- fn from(value: DecompressError) -> Self {
- Self::Decompress(value)
- }
-}
-
-impl From<FromUtf8Error> for ProcessorDeserializeError {
- fn from(value: FromUtf8Error) -> Self {
- Self::FromUtf8(value)
- }
-}
-
-impl fmt::Display for ProcessorDeserializeError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Read(..) => f.write_str("failed to read state data"),
- Self::Decompress(..) => f.write_str("zlib decompression failed"),
- Self::DecompressStall => f.write_str("decompressor stalled before completion"),
- Self::FromUtf8(..) => f.write_str("malformed utf-8 in processor code"),
- Self::Version(ver) => write!(f, "unsupported version ({ver})"),
- Self::CodeLength(len) => write!(f, "invalid code length ({len})"),
- Self::LinkCount(cnt) => write!(f, "invalid link count ({cnt})"),
- }
- }
-}
-
-impl Error for ProcessorDeserializeError {
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- match self {
- Self::Decompress(e) => Some(e),
- Self::FromUtf8(e) => Some(e),
- _ => None,
- }
- }
-}
-
-#[derive(Debug)]
+#[derive(Debug, thiserror::Error)]
pub enum ProcessorSerializeError {
- Write(data::WriteError),
- Compress(CompressError),
- CompressEof(usize),
- CompressStall,
+ #[error("failed to write state data")]
+ Write(#[from] data::WriteError),
+ #[error(transparent)]
+ Compress(#[from] CompressError),
}
impl ProcessorSerializeError {
@@ -392,41 +290,6 @@ impl ProcessorSerializeError {
}
}
-impl From<data::WriteError> for ProcessorSerializeError {
- fn from(value: data::WriteError) -> Self {
- Self::Write(value)
- }
-}
-
-impl From<CompressError> for ProcessorSerializeError {
- fn from(value: CompressError) -> Self {
- Self::Compress(value)
- }
-}
-
-impl fmt::Display for ProcessorSerializeError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::Write(..) => f.write_str("failed to write state data"),
- Self::Compress(..) => f.write_str("zlib compression failed"),
- Self::CompressEof(remain) => write!(
- f,
- "compression overflow with {remain} bytes of input remaining"
- ),
- Self::CompressStall => f.write_str("compressor stalled before completion"),
- }
- }
-}
-
-impl Error for ProcessorSerializeError {
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- match self {
- Self::Compress(e) => Some(e),
- _ => None,
- }
- }
-}
-
#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct ProcessorLink {
name: String,
@@ -529,38 +392,18 @@ impl ProcessorState {
}
}
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
pub enum CodeError {
+ #[error("code too long ({0} bytes)")]
TooLong(usize),
}
-impl fmt::Display for CodeError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::TooLong(len) => write!(f, "code too long ({len} bytes)"),
- }
- }
-}
-
-impl Error for CodeError {}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
pub enum CreateError {
+ #[error("link name too long ({0} bytes)")]
NameLength(usize),
+ #[error("there is already a link named {0}")]
DuplicateName(String),
+ #[error("link {name} already points to ({x}, {y})")]
DuplicatePos { name: String, x: i16, y: i16 },
}
-
-impl fmt::Display for CreateError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::NameLength(len) => write!(f, "link name too long ({len} bytes)"),
- Self::DuplicateName(name) => write!(f, "there already is a link named {name}"),
- Self::DuplicatePos { name, x, y } => {
- write!(f, "link {name} already points to {x} / {y}")
- }
- }
- }
-}
-
-impl Error for CreateError {}