#[cfg(feature = "bevy_reflect")]
use bevy_reflect::prelude::*;
use core::ops::{Deref, DerefMut};
use slotmap::SlotMap;
slotmap::new_key_type! {
pub struct SpanKey;
}
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct Spans(SlotMap<SpanKey, Span>);
impl Deref for Spans {
type Target = SlotMap<SpanKey, Span>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Spans {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Spans {
const DEFAULT_CAPACITY: usize = 1024;
pub(crate) fn with_min_capacity(min_capacity: usize) -> Self {
let capacity = min_capacity.max(Self::DEFAULT_CAPACITY);
Self(SlotMap::with_capacity_and_key(capacity))
}
}
pub(crate) struct SpanBuilder {
pub(crate) min: u16,
pub(crate) max: u16,
pub(crate) area: AreaType,
pub(crate) next: Option<SpanKey>,
}
impl SpanBuilder {
pub(crate) fn build(self) -> Span {
Span {
min: self.min,
max: self.max,
area: self.area,
next: self.next,
}
}
}
impl From<SpanBuilder> for Span {
fn from(builder: SpanBuilder) -> Self {
builder.build()
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct Span {
pub min: u16,
pub max: u16,
pub area: AreaType,
pub next: Option<SpanKey>,
}
impl Span {
pub(crate) const MAX_HEIGHT: u16 = u16::MAX;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[repr(transparent)]
pub struct AreaType(pub u8);
impl Deref for AreaType {
type Target = u8;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for AreaType {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Default for AreaType {
fn default() -> Self {
Self::NOT_WALKABLE
}
}
impl From<u8> for AreaType {
fn from(value: u8) -> Self {
AreaType(value)
}
}
impl AreaType {
pub const NOT_WALKABLE: Self = Self(0);
pub const DEFAULT_WALKABLE: Self = Self(u8::MAX);
#[inline]
pub fn is_walkable(&self) -> bool {
self != &Self::NOT_WALKABLE
}
}
#[cfg(test)]
mod tests {
use super::*;
fn span() -> Span {
SpanBuilder {
min: 2,
max: 10,
area: AreaType(4),
next: None,
}
.build()
}
#[test]
fn can_retrieve_span_data_after_building() {
let span = span();
assert_eq!(span.min, 2);
assert_eq!(span.max, 10);
assert_eq!(span.area, AreaType(4));
assert_eq!(span.next, None);
}
#[test]
fn can_retrieve_span_data_after_setting() {
let mut span = span();
let mut slotmap = SlotMap::with_key();
let span_key: SpanKey = slotmap.insert(span.clone());
span.min = 1;
span.max = 4;
span.area = AreaType(3);
span.next = Some(span_key);
assert_eq!(span.min, 1);
assert_eq!(span.max, 4);
assert_eq!(span.area, AreaType(3));
assert_eq!(span.next, Some(span_key));
}
}