mindustry logic execution, map- and schematic- parsing and rendering
Support Block using a reference to BlockLogic
| -rw-r--r-- | src/access.rs | 128 | ||||
| -rw-r--r-- | src/block/mod.rs | 12 | ||||
| -rw-r--r-- | src/main.rs | 1 |
3 files changed, 133 insertions, 8 deletions
diff --git a/src/access.rs b/src/access.rs new file mode 100644 index 0000000..9b8cc58 --- /dev/null +++ b/src/access.rs @@ -0,0 +1,128 @@ +use std::borrow::Borrow; +use std::cmp::Ordering; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::Deref; + +pub type BoxAccess<'a, D> = Access<'a, Box<D>, D>; + +// Similar to Cow but doesn't require ToOwned +#[derive(Clone, Debug)] +pub enum Access<'a, T: AsRef<B>, B: ?Sized> +{ + Borrowed(&'a B), + Owned(T), +} + +impl<'a, T: AsRef<B>, B> Access<'a, T, B> +{ + pub const fn is_borrowed(&self) -> bool + { + match self + { + Access::Borrowed(..) => true, + _ => false, + } + } + + pub const fn is_owned(&self) -> bool + { + match self + { + Access::Owned(..) => true, + _ => false, + } + } +} + +impl<'a, T: AsRef<B>, B: ?Sized> From<T> for Access<'a, T, B> +{ + fn from(value: T) -> Self + { + Self::Owned(value) + } +} + +impl<'a, T: AsRef<B>, B: ?Sized> AsRef<B> for Access<'a, T, B> +{ + fn as_ref(&self) -> &B + { + self + } +} + +impl<'a, T: AsRef<B>, B: ?Sized> Borrow<B> for Access<'a, T, B> +{ + fn borrow(&self) -> &B + { + match self + { + Access::Borrowed(r) => *r, + Access::Owned(v) => v.as_ref(), + } + } +} + +impl<'a, T: AsRef<B> + Default, B: ?Sized> Default for Access<'a, T, B> +{ + fn default() -> Self + { + Self::Owned(T::default()) + } +} + +impl<'a, T: AsRef<B>, B: ?Sized> Deref for Access<'a, T, B> +{ + type Target = B; + + fn deref(&self) -> &Self::Target + { + match self + { + Access::Borrowed(r) => *r, + Access::Owned(v) => v.as_ref(), + } + } +} + +impl<'a, T: AsRef<B>, B: ?Sized + fmt::Display> fmt::Display for Access<'a, T, B> +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + B::fmt(self, f) + } +} + +impl<'a, T: AsRef<B>, B: ?Sized + Eq> Eq for Access<'a, T, B> {} + +impl<'a, T: AsRef<B>, B: ?Sized + Hash> Hash for Access<'a, T, B> +{ + fn hash<H: Hasher>(&self, state: &mut H) + { + B::hash(self, state) + } +} + +impl<'a, T: AsRef<B>, B: ?Sized + Ord> Ord for Access<'a, T, B> +{ + fn cmp(&self, other: &Self) -> Ordering + { + B::cmp(self, other) + } +} + +impl<'a, 'b, T: AsRef<B>, B: ?Sized + PartialEq<C>, U: AsRef<C>, C: ?Sized> PartialEq<Access<'b, U, C>> for Access<'a, T, B> +{ + fn eq(&self, other: &Access<'b, U, C>) -> bool + { + B::eq(self, other) + } +} + +impl<'a, 'b, T: AsRef<B>, B: ?Sized + PartialOrd<C>, U: AsRef<C>, C: ?Sized> PartialOrd<Access<'b, U, C>> for Access<'a, T, B> +{ + fn partial_cmp(&self, other: &Access<'b, U, C>) -> Option<Ordering> + { + B::partial_cmp(self, other) + } +} diff --git a/src/block/mod.rs b/src/block/mod.rs index 074e431..1a32b6b 100644 --- a/src/block/mod.rs +++ b/src/block/mod.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::collections::hash_map::Entry; +use crate::access::BoxAccess; use crate::data::dynamic::DynData; pub trait BlockLogic @@ -22,12 +23,12 @@ pub trait BlockLogic pub struct Block { name: Cow<'static, str>, - logic: Box<dyn BlockLogic>, + logic: BoxAccess<'static, dyn BlockLogic + Sync>, } impl Block { - pub fn new(name: Cow<'static, str>, logic: Box<dyn BlockLogic>) -> Self + pub const fn new(name: Cow<'static, str>, logic: BoxAccess<'static, dyn BlockLogic + Sync>) -> Self { Self{name, logic} } @@ -152,12 +153,7 @@ impl<'l> BlockRegistry<'l> pub fn register(&mut self, block: &'l Block) -> Result<&'l Block, &'l Block> { - let key = match block.name - { - Cow::Borrowed(r) => r, - Cow::Owned(ref s) => s, - }; - match self.blocks.entry(key) + match self.blocks.entry(&block.name) { Entry::Occupied(e) => Err(e.get()), Entry::Vacant(e) => Ok(*e.insert(block)), diff --git a/src/main.rs b/src/main.rs index b11c58e..90d8d48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +pub mod access; pub mod args; pub mod block; pub mod data; |