mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/item/storage.rs')
-rw-r--r--src/item/storage.rs173
1 files changed, 109 insertions, 64 deletions
diff --git a/src/item/storage.rs b/src/item/storage.rs
index 590c399..45397f5 100644
--- a/src/item/storage.rs
+++ b/src/item/storage.rs
@@ -1,45 +1,98 @@
use std::error::Error;
use std::fmt;
use std::iter::{Enumerate, FusedIterator};
+use std::marker::PhantomData;
use std::slice;
use crate::item;
#[derive(Clone, Debug, Eq)]
-/// holds item counts
-pub struct Storage {
+/// stores data
+pub struct Storage<T> {
base: Vec<u32>,
total: u64,
+ holds: PhantomData<T>,
}
-impl Storage {
- #[must_use]
- pub const fn new() -> Self {
+pub type ItemStorage = Storage<item::Type>;
+
+impl<T> Default for Storage<T> {
+ fn default() -> Self {
Self {
- base: Vec::new(),
+ base: Vec::default(),
total: 0,
+ holds: Default::default(),
}
}
+}
+impl<T> Storage<T>
+where
+ u16: From<T>,
+{
#[must_use]
- pub fn is_empty(&self) -> bool {
- self.total == 0
+ /// create a new storage
+ ///
+ /// ```
+ /// # use mindus::item::storage::ItemStorage;
+ /// // ItemStorage is a alias to Storage<Item>
+ /// let s = ItemStorage::new();
+ /// ```
+ pub fn new() -> Self {
+ Self::default()
}
#[must_use]
- pub fn get_total(&self) -> u64 {
- self.total
+ /// check if its empty
+ ///
+ /// ```
+ /// # use mindus::item::storage::ItemStorage;
+ /// # use mindus::item;
+ ///
+ /// let mut s = ItemStorage::new();
+ /// assert!(s.is_empty());
+ /// s.set(item::Type::Copper, 500);
+ /// assert!(!s.is_empty());
+ /// s.sub(item::Type::Copper, 500, 0);
+ /// assert!(s.is_empty());
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.total == 0
}
+ /// get item count of certain element
+ ///
+ /// ```
+ /// # use mindus::item::storage::ItemStorage;
+ /// # use mindus::item;
+ ///
+ /// let mut s = ItemStorage::new();
+ /// assert!(s.get(item::Type::Coal) == 0);
+ /// s.set(item::Type::Coal, 500);
+ /// assert!(s.get(item::Type::Titanium) == 0);
+ /// assert!(s.get(item::Type::Coal) == 500);
+ /// s.sub(item::Type::Coal, 500, 0);
+ /// assert!(s.get(item::Type::Coal) == 0);
+ /// ```
#[must_use]
- pub fn get(&self, ty: item::Type) -> u32 {
+ pub fn get(&self, ty: T) -> u32 {
match self.base.get(u16::from(ty) as usize) {
None => 0,
Some(cnt) => *cnt,
}
}
-
- pub fn set(&mut self, ty: item::Type, count: u32) -> u32 {
+ /// set item count of certain element
+ ///
+ /// ```
+ /// # use mindus::item::storage::ItemStorage;
+ /// # use mindus::item;
+ ///
+ /// let mut s = ItemStorage::new();
+ /// s.set(item::Type::Coal, 500);
+ /// s.set(item::Type::Copper, 500);
+ /// assert!(s.get(item::Type::Copper) == 500);
+ /// ```
+ pub fn set(&mut self, ty: T, count: u32) -> u32 {
let idx = u16::from(ty) as usize;
match self.base.get_mut(idx) {
None => {
@@ -57,7 +110,21 @@ impl Storage {
}
}
- pub fn add(&mut self, ty: item::Type, add: u32, max: u32) -> (u32, u32) {
+ /// add to a certain elements item count, capping.
+ ///
+ /// ```
+ /// # use mindus::item::storage::ItemStorage;
+ /// # use mindus::item;
+ ///
+ /// let mut s = ItemStorage::new();
+ /// s.add(item::Type::Coal, 500, 500);
+ /// assert!(s.get(item::Type::Coal) == 500);
+ /// s.add(item::Type::Coal, 500, 10000);
+ /// assert!(s.get(item::Type::Coal) == 1000);
+ /// s.add(item::Type::Coal, 500, 1250);
+ /// assert!(s.get(item::Type::Coal) == 1250);
+ /// ```
+ pub fn add(&mut self, ty: T, add: u32, max: u32) -> (u32, u32) {
let idx = u16::from(ty) as usize;
match self.base.get_mut(idx) {
None => {
@@ -80,12 +147,8 @@ impl Storage {
}
}
- pub fn try_add(
- &mut self,
- ty: item::Type,
- add: u32,
- max: u32,
- ) -> Result<(u32, u32), TryAddError> {
+ /// like [`Storage::add`] but fails
+ pub fn try_add(&mut self, ty: T, add: u32, max: u32) -> Result<(u32, u32), TryAddError> {
let idx = u16::from(ty) as usize;
match self.base.get_mut(idx) {
None => {
@@ -95,12 +158,7 @@ impl Storage {
self.total += u64::from(add);
Ok((add, add))
} else {
- Err(TryAddError {
- ty,
- have: 0,
- add,
- max,
- })
+ Err(TryAddError { have: 0, add, max })
}
}
Some(curr) => {
@@ -110,7 +168,6 @@ impl Storage {
Ok((add, *curr))
} else {
Err(TryAddError {
- ty,
have: *curr,
add,
max,
@@ -120,7 +177,7 @@ impl Storage {
}
}
- pub fn sub(&mut self, ty: item::Type, sub: u32, min: u32) -> (u32, u32) {
+ pub fn sub(&mut self, ty: T, sub: u32, min: u32) -> (u32, u32) {
match self.base.get_mut(u16::from(ty) as usize) {
None => (0, 0),
Some(curr) => {
@@ -136,20 +193,10 @@ impl Storage {
}
}
- pub fn try_sub(
- &mut self,
- ty: item::Type,
- sub: u32,
- min: u32,
- ) -> Result<(u32, u32), TrySubError> {
+ pub fn try_sub(&mut self, ty: T, sub: u32, min: u32) -> Result<(u32, u32), TrySubError> {
let idx = u16::from(ty) as usize;
match self.base.get_mut(idx) {
- None => Err(TrySubError {
- ty,
- have: 0,
- sub,
- min,
- }),
+ None => Err(TrySubError { have: 0, sub, min }),
Some(curr) => {
if *curr >= min && *curr - min >= sub {
*curr -= sub;
@@ -157,7 +204,6 @@ impl Storage {
Ok((sub, *curr))
} else {
Err(TrySubError {
- ty,
have: *curr,
sub,
min,
@@ -167,9 +213,9 @@ impl Storage {
}
}
- pub fn add_all(&mut self, other: &Storage, max_each: u32) -> (u64, u64) {
+ pub fn add_all(&mut self, other: &Storage<T>, max_each: u32) -> (u64, u64) {
let mut added = 0u64;
- if max_each > 0 && other.get_total() > 0 {
+ if max_each > 0 && other.total > 0 {
let mut iter = other.base.iter().enumerate();
// resize our vector only once and if necessary
let (last, add_last) = iter.rfind(|(_, n)| **n != 0).unwrap();
@@ -198,9 +244,9 @@ impl Storage {
(added, self.total)
}
- pub fn pull_all(&mut self, other: &mut Storage, max_each: u32) -> (u64, u64, u64) {
+ pub fn pull_all(&mut self, other: &mut Storage<T>, max_each: u32) -> (u64, u64, u64) {
let mut added = 0u64;
- if max_each > 0 && other.get_total() > 0 {
+ if max_each > 0 && other.total > 0 {
let mut iter = other.base.iter_mut().enumerate();
// resize our vector only once and if necessary
let (last, add_last) = iter.rfind(|(_, n)| **n != 0).unwrap();
@@ -232,9 +278,9 @@ impl Storage {
(added, self.total, other.total)
}
- pub fn sub_all(&mut self, other: &Storage, min_each: u32) -> (u64, u64) {
+ pub fn sub_all(&mut self, other: &Storage<T>, min_each: u32) -> (u64, u64) {
let mut subbed = 0u64;
- if self.get_total() > 0 && other.get_total() > 0 {
+ if self.total > 0 && other.total > 0 {
// no need for resizing, we only remove
// process items by increasing ID
for (idx, sub) in other.base.iter().enumerate() {
@@ -254,9 +300,9 @@ impl Storage {
(subbed, self.total)
}
- pub fn diff_all(&mut self, other: &mut Storage, min_each: u32) -> (u64, u64, u64) {
+ pub fn diff_all(&mut self, other: &mut Storage<T>, min_each: u32) -> (u64, u64, u64) {
let mut subbed = 0u64;
- if self.get_total() > 0 && other.get_total() > 0 {
+ if self.total > 0 && other.total > 0 {
// no need for resizing, we only remove
// consider only indexes present in both
let end = self.base.len().min(other.base.len());
@@ -300,7 +346,7 @@ impl Storage {
}
// manual because padding with zeros doesn't affect equality
-impl PartialEq for Storage {
+impl<T> PartialEq for Storage<T> {
fn eq(&self, other: &Self) -> bool {
let mut li = self.base.iter().fuse();
let mut ri = other.base.iter().fuse();
@@ -317,16 +363,17 @@ impl PartialEq for Storage {
}
}
-impl fmt::Display for Storage {
+impl<T> fmt::Display for Storage<T>
+where
+ u16: From<T>,
+{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let mut first = true;
- for (ty, cnt) in self.iter_nonzero() {
- if first {
- first = false;
- } else {
- f.write_str(", ")?;
- }
+ let mut iter = self.iter_nonzero();
+ if let Some((ty, cnt)) = iter.next() {
write!(f, "{cnt} {ty}")?;
+ for (ty, cnt) in iter {
+ write!(f, ", {cnt} {ty}")?;
+ }
}
Ok(())
}
@@ -334,7 +381,6 @@ impl fmt::Display for Storage {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TryAddError {
- pub ty: item::Type,
pub have: u32,
pub add: u32,
pub max: u32,
@@ -344,8 +390,8 @@ impl fmt::Display for TryAddError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
- "adding {} {:?} to current {} would exceed {}",
- self.add, self.ty, self.have, self.max
+ "adding {:?} to current {} would exceed {}",
+ self.add, self.have, self.max
)
}
}
@@ -354,7 +400,6 @@ impl Error for TryAddError {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TrySubError {
- pub ty: item::Type,
pub have: u32,
pub sub: u32,
pub min: u32,
@@ -364,8 +409,8 @@ impl fmt::Display for TrySubError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
- "removing {} {:?} from current {} would drop below {}",
- self.sub, self.ty, self.have, self.min
+ "removing {} from current {} would drop below {}",
+ self.sub, self.have, self.min
)
}
}