mindustry logic execution, map- and schematic- parsing and rendering
remove lifetimes
bendn 2023-09-14
parent 6cf0bbb · commit 5c918de
-rw-r--r--mindus/Cargo.toml2
-rw-r--r--mindus/src/block/production.rs2
-rw-r--r--mindus/src/data/autotile.rs14
-rw-r--r--mindus/src/data/map.rs54
-rw-r--r--mindus/src/data/renderer.rs4
-rw-r--r--mindus/src/data/schematic.rs56
-rw-r--r--mindus/src/item/storage.rs48
7 files changed, 97 insertions, 83 deletions
diff --git a/mindus/Cargo.toml b/mindus/Cargo.toml
index c7411cd..bc1a042 100644
--- a/mindus/Cargo.toml
+++ b/mindus/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mindus"
-version = "4.0.18"
+version = "5.0.1"
edition = "2021"
description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)"
authors = [
diff --git a/mindus/src/block/production.rs b/mindus/src/block/production.rs
index 9e97bf2..b20f121 100644
--- a/mindus/src/block/production.rs
+++ b/mindus/src/block/production.rs
@@ -27,7 +27,7 @@ make_simple!(
unsafe { base.overlay(&ozone) };
base
},
- |b: &mut Build<'_>, buff: &mut DataRead| {
+ |b: &mut Build, buff: &mut DataRead| {
// format:
// - progress: `f32`
// - warmup: `f32`
diff --git a/mindus/src/data/autotile.rs b/mindus/src/data/autotile.rs
index 59a6010..f8021f3 100644
--- a/mindus/src/data/autotile.rs
+++ b/mindus/src/data/autotile.rs
@@ -46,11 +46,11 @@ pub(crate) use define;
#[cfg(test)]
pub(crate) use dir;
-pub type Cross<'l> = [Option<(&'l Block, Rotation)>; 4];
+pub type Cross = [Option<(&'static Block, Rotation)>; 4];
/// holds the 4 bordering blocks
#[derive(Copy, Clone)]
-pub struct RenderingContext<'l> {
- pub cross: Cross<'l>,
+pub struct RenderingContext {
+ pub cross: Cross,
pub position: PositionContext,
}
@@ -73,7 +73,7 @@ impl std::fmt::Debug for PositionContext {
}
#[cfg(test)]
-fn print_crosses(v: Vec<Cross<'_>>, height: usize) -> String {
+fn print_crosses(v: Vec<Cross>, height: usize) -> String {
let mut s = String::new();
for c in v.chunks(height) {
for c in c {
@@ -89,7 +89,7 @@ fn print_crosses(v: Vec<Cross<'_>>, height: usize) -> String {
s
}
-pub fn tile(ctx: &RenderingContext<'_>, name: &str, rot: Rotation, s: Scale) -> ImageHolder<4> {
+pub fn tile(ctx: &RenderingContext, name: &str, rot: Rotation, s: Scale) -> ImageHolder<4> {
mask2tile(mask(ctx, rot, name), rot, name, s)
}
@@ -224,8 +224,8 @@ pub fn mask(ctx: &RenderingContext, rot: Rotation, n: &str) -> U4 {
pub trait RotationState {
fn get_rotation(&self) -> Option<Rotation>;
}
-pub trait BlockState<'l> {
- fn get_block(&'l self) -> Option<&'l Block>;
+pub trait BlockState {
+ fn get_block(&self) -> Option<&'static Block>;
}
pub trait Crossable {
fn cross(&self, j: usize, c: &PositionContext) -> Cross;
diff --git a/mindus/src/data/map.rs b/mindus/src/data/map.rs
index c58fbbc..b29ffd8 100644
--- a/mindus/src/data/map.rs
+++ b/mindus/src/data/map.rs
@@ -90,10 +90,10 @@ use crate::content::Content;
/// a tile in a map
#[derive(Clone)]
-pub struct Tile<'l> {
+pub struct Tile {
pub floor: BlockEnum,
pub ore: BlockEnum,
- build: Option<Build<'l>>,
+ build: Option<Build>,
}
macro_rules! lo {
@@ -105,7 +105,7 @@ macro_rules! lo {
} };
}
-impl<'l> Tile<'l> {
+impl Tile {
#[must_use]
pub const fn new(floor: BlockEnum, ore: BlockEnum) -> Self {
Self {
@@ -115,7 +115,7 @@ impl<'l> Tile<'l> {
}
}
- fn set_block(&mut self, block: &'l Block) {
+ fn set_block(&mut self, block: &'static Block) {
self.build = Some(Build {
block,
state: None,
@@ -128,7 +128,7 @@ impl<'l> Tile<'l> {
}
#[must_use]
- pub const fn build(&self) -> Option<&Build<'l>> {
+ pub const fn build(&self) -> Option<&Build> {
self.build.as_ref()
}
@@ -217,7 +217,7 @@ impl<'l> Tile<'l> {
}
}
-impl std::fmt::Debug for Tile<'_> {
+impl std::fmt::Debug for Tile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
@@ -237,34 +237,34 @@ impl std::fmt::Debug for Tile<'_> {
}
}
-impl<'l> BlockState<'l> for Tile<'l> {
- fn get_block(&self) -> Option<&'l Block> {
+impl BlockState for Tile {
+ fn get_block(&self) -> Option<&'static Block> {
Some(self.build()?.block)
}
}
-impl RotationState for Tile<'_> {
+impl RotationState for Tile {
fn get_rotation(&self) -> Option<Rotation> {
Some(self.build()?.rotation)
}
}
-impl RotationState for Option<Tile<'_>> {
+impl RotationState for Option<Tile> {
fn get_rotation(&self) -> Option<Rotation> {
self.as_ref().unwrap().get_rotation()
}
}
-impl<'l> BlockState<'l> for Option<Tile<'_>> {
- fn get_block(&'l self) -> Option<&'l Block> {
+impl BlockState for Option<Tile> {
+ fn get_block(&self) -> Option<&'static Block> {
self.as_ref().unwrap().get_block()
}
}
/// a build on a tile in a map
#[derive(Clone)]
-pub struct Build<'l> {
- pub block: &'l Block,
+pub struct Build {
+ pub block: &'static Block,
pub items: Storage<Item>,
pub liquids: Storage<Fluid>,
pub state: Option<State>,
@@ -274,15 +274,15 @@ pub struct Build<'l> {
pub data: i8,
}
-impl std::fmt::Debug for Build<'_> {
+impl std::fmt::Debug for Build {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Build<{block}>", block = self.block.name(),)
}
}
-impl<'l> Build<'l> {
+impl Build {
#[must_use]
- pub fn new(block: &'l Block) -> Build<'l> {
+ pub fn new(block: &'static Block) -> Build {
Self {
block,
items: Storage::default(),
@@ -420,7 +420,7 @@ fn test_read_liquids() {
/// a map.
/// ## Does not support serialization yet!
#[derive(Debug)]
-pub struct Map<'l> {
+pub struct Map {
pub width: usize,
pub height: usize,
pub tags: HashMap<String, String>,
@@ -431,7 +431,7 @@ pub struct Map<'l> {
/// (0, 1), (1, 1), (2, 1)
/// (0, 2), (1, 2), (2, 2)
/// ```
- pub tiles: Vec<Tile<'l>>,
+ pub tiles: Vec<Tile>,
}
macro_rules! cond {
@@ -444,7 +444,7 @@ macro_rules! cond {
};
}
-impl<'l> Crossable for Map<'l> {
+impl Crossable for Map {
fn cross(&self, j: usize, c: &PositionContext) -> Cross {
let get = |i| {
let b = &self[i];
@@ -462,7 +462,7 @@ impl<'l> Crossable for Map<'l> {
}
}
-impl<'l> Map<'l> {
+impl Map {
#[must_use]
pub fn new(width: usize, height: usize, tags: HashMap<String, String>) -> Self {
Self {
@@ -474,19 +474,19 @@ impl<'l> Map<'l> {
}
}
- fn push(&mut self, t: Tile<'l>) {
+ fn push(&mut self, t: Tile) {
self.tiles.push(t);
}
}
-impl<'l> Index<usize> for Map<'l> {
- type Output = Tile<'l>;
+impl Index<usize> for Map {
+ type Output = Tile;
fn index(&self, index: usize) -> &Self::Output {
&self.tiles[index]
}
}
-impl<'l> IndexMut<usize> for Map<'l> {
+impl IndexMut<usize> for Map {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.tiles[index]
}
@@ -512,7 +512,7 @@ pub enum ReadError {
}
/// serde map
-impl<'l> Serializable for Map<'l> {
+impl Serializable for Map {
type ReadError = ReadError;
type WriteError = ();
/// deserialize a map
@@ -520,7 +520,7 @@ impl<'l> Serializable for Map<'l> {
/// notes:
/// - does not deserialize data
/// - does not deserialize entities
- fn deserialize(buff: &mut DataRead<'_>) -> Result<Map<'l>, Self::ReadError> {
+ fn deserialize(buff: &mut DataRead<'_>) -> Result<Map, Self::ReadError> {
let buff = buff.deflate()?;
let mut buff = DataRead::new(&buff);
{
diff --git a/mindus/src/data/renderer.rs b/mindus/src/data/renderer.rs
index 5fa5556..e68c96a 100644
--- a/mindus/src/data/renderer.rs
+++ b/mindus/src/data/renderer.rs
@@ -84,7 +84,7 @@ pub trait Renderable {
fn render(&self) -> Image<Vec<u8>, 3>;
}
-impl Renderable for Schematic<'_> {
+impl Renderable for Schematic {
/// creates a picture of a schematic. Bridges and node connections are not drawn.
/// ```
/// # use mindus::*;
@@ -151,7 +151,7 @@ impl Renderable for Schematic<'_> {
}
}
-impl Renderable for Map<'_> {
+impl Renderable for Map {
/// Draws a map
fn render(&self) -> Image<Vec<u8>, 3> {
let scale = if self.width + self.height < 2000 {
diff --git a/mindus/src/data/schematic.rs b/mindus/src/data/schematic.rs
index d324d7f..48e388f 100644
--- a/mindus/src/data/schematic.rs
+++ b/mindus/src/data/schematic.rs
@@ -19,28 +19,28 @@ pub const MAX_BLOCKS: u32 = 256 * 256;
/// a placement in a schematic
#[derive(Clone)]
-pub struct Placement<'l> {
- pub block: &'l Block,
+pub struct Placement {
+ pub block: &'static Block,
pub rot: Rotation,
state: Option<State>,
}
-impl PartialEq for Placement<'_> {
- fn eq(&self, rhs: &Placement<'_>) -> bool {
+impl PartialEq for Placement {
+ fn eq(&self, rhs: &Placement) -> bool {
self.block == rhs.block && self.rot == rhs.rot
}
}
-impl fmt::Debug for Placement<'_> {
+impl fmt::Debug for Placement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "P<{}[*{}]>", self.block.name(), self.rot.ch())
}
}
-impl<'l> Placement<'l> {
+impl Placement {
/// make a placement from a block
#[must_use]
- pub const fn new(block: &'l Block) -> Self {
+ pub const fn new(block: &'static Block) -> Self {
Self {
block,
rot: Rotation::Up,
@@ -82,20 +82,20 @@ impl<'l> Placement<'l> {
}
}
-impl<'l> BlockState<'l> for Placement<'l> {
- fn get_block(&self) -> Option<&'l Block> {
+impl BlockState for Placement {
+ fn get_block(&self) -> Option<&'static Block> {
Some(self.block)
}
}
-impl RotationState for Placement<'_> {
+impl RotationState for Placement {
fn get_rotation(&self) -> Option<Rotation> {
Some(self.rot)
}
}
-impl<'l> BlockState<'l> for Option<Placement<'l>> {
- fn get_block(&self) -> Option<&'l Block> {
+impl BlockState for Option<Placement> {
+ fn get_block(&self) -> Option<&'static Block> {
let Some(p) = self else {
return None;
};
@@ -103,7 +103,7 @@ impl<'l> BlockState<'l> for Option<Placement<'l>> {
}
}
-impl RotationState for Option<Placement<'_>> {
+impl RotationState for Option<Placement> {
fn get_rotation(&self) -> Option<Rotation> {
let Some(p) = self else {
return None;
@@ -114,16 +114,16 @@ impl RotationState for Option<Placement<'_>> {
#[derive(Clone, Debug)]
/// a schematic.
-pub struct Schematic<'l> {
+pub struct Schematic {
pub width: usize,
pub height: usize,
pub tags: HashMap<String, String>,
/// schems can have holes, so [Option] is used.
- pub blocks: Array2D<Option<Placement<'l>>>,
+ pub blocks: Array2D<Option<Placement>>,
}
-impl<'l> PartialEq for Schematic<'l> {
- fn eq(&self, rhs: &Schematic<'l>) -> bool {
+impl PartialEq for Schematic {
+ fn eq(&self, rhs: &Schematic) -> bool {
self.width == rhs.width
&& self.height == rhs.height
&& self.blocks == rhs.blocks
@@ -131,7 +131,7 @@ impl<'l> PartialEq for Schematic<'l> {
}
}
-impl<'l> Schematic<'l> {
+impl Schematic {
#[must_use]
/// create a new schematic, panicking if too big
/// ```
@@ -238,7 +238,7 @@ impl<'l> Schematic<'l> {
/// s.put(0, 0, &DUO);
/// assert!(s.get(0, 0).unwrap().is_some());
/// ```
- pub fn get(&self, x: usize, y: usize) -> Result<Option<&Placement<'l>>, PosError> {
+ pub fn get(&self, x: usize, y: usize) -> Result<Option<&Placement>, PosError> {
if x >= self.width || y >= self.height {
return Err(PosError {
x,
@@ -251,7 +251,7 @@ impl<'l> Schematic<'l> {
}
/// gets a block, mutably
- pub fn get_mut(&mut self, x: usize, y: usize) -> Result<Option<&mut Placement<'l>>, PosError> {
+ pub fn get_mut(&mut self, x: usize, y: usize) -> Result<Option<&mut Placement>, PosError> {
if x >= self.width || y >= self.height {
return Err(PosError {
x,
@@ -272,7 +272,7 @@ impl<'l> Schematic<'l> {
/// s.put(0, 0, &ROUTER);
/// assert!(s.get(0, 0).unwrap().is_some() == true);
/// ```
- pub fn put(&mut self, x: usize, y: usize, block: &'l Block) -> &mut Self {
+ pub fn put(&mut self, x: usize, y: usize, block: &'static Block) -> &mut Self {
self.set(x, y, block, DynData::Empty, Rotation::Up).unwrap();
self
}
@@ -292,7 +292,7 @@ impl<'l> Schematic<'l> {
&mut self,
x: usize,
y: usize,
- block: &'l Block,
+ block: &'static Block,
data: DynData,
rot: Rotation,
) -> Result<(), PlaceError> {
@@ -334,7 +334,7 @@ impl<'l> Schematic<'l> {
/// assert!(s.take(0, 0).unwrap().is_some() == true);
/// assert!(s.get(0, 0).unwrap().is_none() == true);
/// ```
- pub fn take(&mut self, x: usize, y: usize) -> Result<Option<Placement<'l>>, PosError> {
+ pub fn take(&mut self, x: usize, y: usize) -> Result<Option<Placement>, PosError> {
if x >= self.width || y >= self.height {
return Err(PosError {
x,
@@ -348,7 +348,7 @@ impl<'l> Schematic<'l> {
}
/// iterate over all the blocks
- pub fn block_iter(&self) -> impl Iterator<Item = (GridPos, &Placement<'_>)> {
+ pub fn block_iter(&self) -> impl Iterator<Item = (GridPos, &Placement)> {
self.blocks.iter().enumerate().filter_map(|(i, p)| {
let Some(p) = p else {
return None;
@@ -471,10 +471,10 @@ impl fmt::Display for TruncatedError {
const SCHEMATIC_HEADER: u32 =
((b'm' as u32) << 24) | ((b's' as u32) << 16) | ((b'c' as u32) << 8) | (b'h' as u32);
-impl<'l> Serializable for Schematic<'l> {
+impl Serializable for Schematic {
type ReadError = ReadError;
type WriteError = WriteError;
- fn deserialize(buff: &mut DataRead<'_>) -> Result<Schematic<'l>, Self::ReadError> {
+ fn deserialize(buff: &mut DataRead<'_>) -> Result<Schematic, Self::ReadError> {
let hdr = buff.read_u32()?;
if hdr != SCHEMATIC_HEADER {
return Err(ReadError::Header(hdr));
@@ -624,7 +624,7 @@ pub enum WriteError {
Compress(#[from] super::CompressError),
}
-impl<'l> Schematic<'l> {
+impl Schematic {
/// deserializes a schematic from base64
/// ```
/// # use mindus::*;
@@ -632,7 +632,7 @@ impl<'l> Schematic<'l> {
/// let s = Schematic::deserialize_base64(string).unwrap();
/// assert!(s.get(1, 1).unwrap().unwrap().block.name() == "payload-router");
/// ```
- pub fn deserialize_base64(data: &str) -> Result<Schematic<'l>, R64Error> {
+ pub fn deserialize_base64(data: &str) -> Result<Schematic, R64Error> {
let mut buff = vec![0; data.len() / 4 * 3 + 1];
let n_out = base64::decode(data.as_bytes(), buff.as_mut())?;
Ok(Self::deserialize(&mut DataRead::new(&buff[..n_out]))?)
diff --git a/mindus/src/item/storage.rs b/mindus/src/item/storage.rs
index 8cf3c16..9397b14 100644
--- a/mindus/src/item/storage.rs
+++ b/mindus/src/item/storage.rs
@@ -330,25 +330,27 @@ where
(subbed, self.total, other.total)
}
- #[must_use]
- pub fn iter(&self) -> Iter<'_> {
+ pub fn clear(&mut self) {
+ self.base.clear();
+ }
+}
+
+impl<T: TryFrom<u16>> Storage<T> {
+ pub fn iter(&self) -> Iter<'_, T> {
Iter {
base: self.base.iter().enumerate(),
all: true,
+ _t: PhantomData,
}
}
- #[must_use]
- pub fn iter_nonzero(&self) -> Iter<'_> {
+ pub fn iter_nonzero(&self) -> Iter<'_, T> {
Iter {
base: self.base.iter().enumerate(),
all: false,
+ _t: PhantomData,
}
}
-
- pub fn clear(&mut self) {
- self.base.clear();
- }
}
// manual because padding with zeros doesn't affect equality
@@ -369,10 +371,7 @@ impl<T> PartialEq for Storage<T> {
}
}
-impl<T> fmt::Display for Storage<T>
-where
- u16: From<T>,
-{
+impl<T: TryFrom<u16> + fmt::Display> fmt::Display for Storage<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut iter = self.iter_nonzero();
if let Some((ty, cnt)) = iter.next() {
@@ -401,19 +400,31 @@ pub struct TrySubError {
pub min: u32,
}
+impl<'l, T: TryFrom<u16>> IntoIterator for &'l Storage<T> {
+ type Item = (T, u32);
+
+ type IntoIter = Iter<'l, T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
#[derive(Clone, Debug)]
-pub struct Iter<'l> {
+#[must_use = "iterator is lazy"]
+pub struct Iter<'l, T: TryFrom<u16>> {
base: Enumerate<slice::Iter<'l, u32>>,
all: bool,
+ _t: PhantomData<T>,
}
-impl<'l> Iterator for Iter<'l> {
- type Item = (item::Type, u32);
+impl<'l, T: TryFrom<u16>> Iterator for Iter<'l, T> {
+ type Item = (T, u32);
fn next(&mut self) -> Option<Self::Item> {
for (idx, cnt) in self.base.by_ref() {
if *cnt > 0 || self.all {
- if let Ok(ty) = item::Type::try_from(idx as u16) {
+ if let Ok(ty) = T::try_from(idx as u16) {
return Some((ty, *cnt));
}
}
@@ -426,4 +437,7 @@ impl<'l> Iterator for Iter<'l> {
}
}
-impl<'l> FusedIterator for Iter<'l> where Enumerate<slice::Iter<'l, u32>>: FusedIterator {}
+impl<'l, T: TryFrom<u16>> FusedIterator for Iter<'l, T> where
+ Enumerate<slice::Iter<'l, u32>>: FusedIterator
+{
+}