mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/data/schematic.rs')
| -rw-r--r-- | src/data/schematic.rs | 139 |
1 files changed, 18 insertions, 121 deletions
diff --git a/src/data/schematic.rs b/src/data/schematic.rs index 5465498..19026f2 100644 --- a/src/data/schematic.rs +++ b/src/data/schematic.rs @@ -6,10 +6,6 @@ use std::fmt::{self, Write}; use std::iter::FusedIterator; use std::slice::Iter; -use flate2::{ - Compress, CompressError, Compression, Decompress, DecompressError, FlushCompress, - FlushDecompress, Status, -}; use image::RgbaImage; use crate::block::{self, Block, BlockRegistry, Rotation, State}; @@ -1015,72 +1011,45 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { if version > 1 { return Err(ReadError::Version(version)); } - 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(buff.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 - buff.data = &buff.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(ReadError::DecompressStall); - } - raw.reserve(1024); - } - assert_eq!(dec.total_out() as usize, raw.len()); - let mut rbuff = DataRead::new(&raw); - let w = rbuff.read_i16()?; - let h = rbuff.read_i16()?; + let mut buff = buff.deflate()?; + let mut buff = DataRead::new(&mut buff); + let w = buff.read_i16()?; + let h = buff.read_i16()?; if w < 0 || h < 0 || w as u16 > MAX_DIMENSION || h as u16 > MAX_DIMENSION { return Err(ReadError::Dimensions(w, h)); } let mut schematic = Schematic::new(w as u16, h as u16); - for _ in 0..rbuff.read_u8()? { - let key = rbuff.read_utf()?; - let value = rbuff.read_utf()?; - schematic.tags.insert(key.to_owned(), value.to_owned()); - } - let num_table = rbuff.read_i8()?; + buff.read_map(&mut schematic.tags)?; + let num_table = buff.read_i8()?; if num_table < 0 { return Err(ReadError::TableSize(num_table)); } - let mut block_table = Vec::<&'l Block>::new(); + let mut block_table = Vec::new(); block_table.reserve(num_table as usize); for _ in 0..num_table { - let name = rbuff.read_utf()?; - match self.0.get(name) { + let name = buff.read_utf()?; + match self.0.get(&name) { None => return Err(ReadError::NoSuchBlock(name.to_owned())), Some(b) => block_table.push(b), } } - let num_blocks = rbuff.read_i32()?; + let num_blocks = buff.read_i32()?; if num_blocks < 0 || num_blocks as u32 > MAX_BLOCKS { return Err(ReadError::BlockCount(num_blocks)); } for _ in 0..num_blocks { - let idx = rbuff.read_i8()?; + let idx = buff.read_i8()?; if idx < 0 || idx as usize >= block_table.len() { return Err(ReadError::BlockIndex(idx, block_table.len())); } - let pos = GridPos::from(rbuff.read_u32()?); + let pos = GridPos::from(buff.read_u32()?); let block = block_table[idx as usize]; let config = if version < 1 { - block.data_from_i32(rbuff.read_i32()?, pos)? + block.data_from_i32(buff.read_i32()?, pos)? } else { - DynSerializer.deserialize(&mut rbuff)? + DynSerializer.deserialize(&mut buff)? }; - let rot = Rotation::from(rbuff.read_u8()?); + let rot = Rotation::from(buff.read_u8()?); schematic.set(pos.0, pos.1, block, config, rot)?; } Ok(schematic) @@ -1108,8 +1077,8 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { rbuff.write_utf(v)?; } // use string keys here to avoid issues with different block refs with the same name - let mut block_map = HashMap::<&str, u32>::new(); - let mut block_table = Vec::<&str>::new(); + let mut block_map = HashMap::new(); + let mut block_table = Vec::new(); for curr in &data.blocks { if let Entry::Vacant(e) = block_map.entry(curr.block.get_name()) { e.insert(block_table.len() as u32); @@ -1139,52 +1108,7 @@ impl<'l> Serializer<Schematic<'l>> for SchematicSerializer<'l> { num += 1; } assert_eq!(num, data.blocks.len()); - - // compress into the provided buffer - let data::WriteBuff::Vec(raw) = rbuff.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 buff.data { - 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(WriteError::CompressEof( - raw.len() - comp.total_in() as usize, - )) - } - Status::StreamEnd => (), - } - } - data::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(WriteError::CompressStall); - } - dst.reserve(1024); - } - } - } - assert_eq!(comp.total_in() as usize, raw.len()); + rbuff.inflate(buff)?; Ok(()) } } @@ -1194,8 +1118,6 @@ pub enum ReadError { Read(data::ReadError), Header(u32), Version(u8), - Decompress(DecompressError), - DecompressStall, Dimensions(i16, i16), TableSize(i8), NoSuchBlock(String), @@ -1212,12 +1134,6 @@ impl From<data::ReadError> for ReadError { } } -impl From<DecompressError> for ReadError { - fn from(value: DecompressError) -> Self { - Self::Decompress(value) - } -} - impl From<dynamic::ReadError> for ReadError { fn from(value: dynamic::ReadError) -> Self { Self::ReadState(value) @@ -1242,8 +1158,6 @@ impl fmt::Display for ReadError { Self::Read(..) => f.write_str("failed to read from buffer"), Self::Header(hdr) => write!(f, "incorrect header ({hdr:08X})"), Self::Version(ver) => write!(f, "unsupported version ({ver})"), - Self::Decompress(..) => f.write_str("zlib decompression failed"), - Self::DecompressStall => f.write_str("decompressor stalled before completion"), Self::Dimensions(w, h) => write!(f, "invalid schematic dimensions ({w} * {h})"), Self::TableSize(cnt) => write!(f, "invalid block table size ({cnt})"), Self::NoSuchBlock(name) => write!(f, "unknown block {name:?}"), @@ -1260,7 +1174,6 @@ impl Error for ReadError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { Self::Read(e) => Some(e), - Self::Decompress(e) => Some(e), Self::BlockConfig(e) => Some(e), Self::ReadState(e) => Some(e), Self::Placement(e) => Some(e), @@ -1276,9 +1189,6 @@ pub enum WriteError { TableSize(usize), StateSerialize(block::SerializeError), WriteState(dynamic::WriteError), - Compress(CompressError), - CompressEof(usize), - CompressStall, } impl From<data::WriteError> for WriteError { @@ -1293,12 +1203,6 @@ impl From<block::SerializeError> for WriteError { } } -impl From<CompressError> for WriteError { - fn from(value: CompressError) -> Self { - Self::Compress(value) - } -} - impl From<dynamic::WriteError> for WriteError { fn from(value: dynamic::WriteError) -> Self { Self::WriteState(value) @@ -1313,12 +1217,6 @@ impl fmt::Display for WriteError { Self::TableSize(len) => write!(f, "block table too long ({len})"), Self::StateSerialize(e) => e.fmt(f), Self::WriteState(..) => f.write_str("failed to write block 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"), } } } @@ -1328,7 +1226,6 @@ impl Error for WriteError { match self { Self::Write(e) => Some(e), Self::StateSerialize(e) => e.source(), - Self::Compress(e) => Some(e), _ => None, } } |