137 Zeilen
4,2 KiB
Rust
137 Zeilen
4,2 KiB
Rust
use super::Kartesian;
|
|
|
|
/// Rust implementation of an Map. The Zeropoint is Topleft
|
|
/// The Rows in the data are not nessesaryly in the specifed length, should values be missing, then there are functions that returns
|
|
#[derive(Debug, Clone)]
|
|
pub struct Map<T: Clone + Copy> {
|
|
pub(super) maximum: Kartesian<usize>,
|
|
pub(super) data: Vec<Vec<T>>,
|
|
}
|
|
|
|
impl<T: Clone + Copy> Map<T> {
|
|
/// creates an empty Map
|
|
pub fn empty(length: usize, height: usize) -> Self {
|
|
Self {
|
|
data: Vec::new(),
|
|
maximum: Kartesian::new(height, length),
|
|
}
|
|
}
|
|
|
|
pub fn size(&self) -> Kartesian<usize> {
|
|
self.maximum
|
|
}
|
|
|
|
/// returns true if coordinates are outside of bounds
|
|
#[inline]
|
|
fn outside(&self, coord: Kartesian<usize>) -> bool {
|
|
coord.x >= self.maximum.x || coord.y >= self.maximum.y
|
|
}
|
|
|
|
/// Unsafe Version of the get or get_wrapping functions.
|
|
/// It does not check against an missing value and panics if its out of bounds.
|
|
#[inline]
|
|
pub unsafe fn get_unsafe(&self, coord: Kartesian<usize>) -> T {
|
|
if self.outside(coord) {
|
|
panic!("Coordinates out of bounds: {} >= {}", coord, self.maximum)
|
|
}
|
|
self.data[coord.x][coord.y]
|
|
}
|
|
}
|
|
|
|
impl<T: Copy + Copy + Default + PartialEq> Map<T> {
|
|
/// Returns an Option Containing the value.
|
|
/// Returns None if out of bounds or not yet set.
|
|
pub fn get(&self, coord: Kartesian<usize>) -> Option<T> {
|
|
if self.outside(coord) {
|
|
return None;
|
|
}
|
|
if coord.x >= self.data.len() {
|
|
Some(T::default())
|
|
} else if coord.y >= self.data[coord.x].len() {
|
|
Some(T::default())
|
|
} else {
|
|
Some(self.data[coord.x][coord.y])
|
|
}
|
|
}
|
|
|
|
/// Replaces unset and default values with
|
|
pub fn replace_default(&mut self, new_value: T) {
|
|
for row in self.data.iter_mut() {
|
|
*row = row
|
|
.iter()
|
|
.map(|c| {
|
|
if *c == T::default() {
|
|
new_value
|
|
} else {
|
|
*c
|
|
}
|
|
})
|
|
.collect();
|
|
if row.len() < self.maximum.y {
|
|
row.resize(self.maximum.y, new_value);
|
|
}
|
|
}
|
|
if self.data.len() < self.maximum.x {
|
|
let full_row = vec![new_value; self.maximum.y];
|
|
self.data.resize(self.maximum.x, full_row);
|
|
}
|
|
}
|
|
|
|
/// Returns the value of in the map.
|
|
#[inline]
|
|
pub fn wrapping_get(&self, coord: Kartesian<usize>) -> T {
|
|
let modded = coord % self.maximum;
|
|
if modded.x >= self.data.len() {
|
|
T::default()
|
|
} else if modded.y >= self.data[modded.x].len() {
|
|
T::default()
|
|
} else {
|
|
self.data[modded.x][modded.y]
|
|
}
|
|
}
|
|
|
|
pub fn set(&mut self, coord: Kartesian<usize>, value: T) -> T {
|
|
if self.outside(coord) {
|
|
panic!("Coordinates outside of bounds: {} >= {}", coord, self.maximum)
|
|
}
|
|
if self.data.len() < coord.x + 1 {
|
|
self.data.resize(coord.x + 1, Vec::new());
|
|
}
|
|
if self.data[coord.x].len() < coord.y + 1 {
|
|
self.data[coord.x].resize(coord.y + 1, T::default());
|
|
}
|
|
let oldvalue = self.data[coord.x][coord.y];
|
|
self.data[coord.x][coord.y] = value;
|
|
oldvalue
|
|
}
|
|
|
|
pub fn extend_left(&mut self, amount: usize) {
|
|
for line in self.data.iter_mut() {
|
|
for _ in 0..amount {
|
|
line.insert(0, T::default());
|
|
}
|
|
}
|
|
self.maximum.y += amount;
|
|
}
|
|
pub fn extend_right(&mut self, amount: usize) {
|
|
self.maximum.y += amount;
|
|
}
|
|
pub fn extend_up(&mut self, amount: usize) {
|
|
for _ in 0..amount {
|
|
self.data.insert(0, Vec::new());
|
|
}
|
|
self.maximum.x += amount
|
|
}
|
|
pub fn extend_down(&mut self, amount: usize) {
|
|
self.maximum.x += amount
|
|
}
|
|
}
|
|
|
|
impl<T: Clone + Copy> From<Vec<Vec<T>>> for Map<T> {
|
|
fn from(value: Vec<Vec<T>>) -> Self {
|
|
Map {
|
|
data: value.clone(),
|
|
maximum: Kartesian::new(value.len(), value.iter().map(|line| line.len()).max().unwrap_or(0)),
|
|
}
|
|
}
|
|
}
|