use std::mem;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Cardinal {
S = 0,
E = 1,
N = 2,
W = 3,
}
impl Cardinal {
pub fn from_index(i: u8) -> Cardinal {
match i {
0 => Cardinal::S,
1 => Cardinal::E,
2 => Cardinal::N,
3 => Cardinal::W,
_ => panic!(
"Wrong Cardinal index: Expected value in [0, 3]; Actual value {}.",
i
),
}
}
pub(crate) fn index(&self) -> u8 {
(*self) as u8
}
pub(super) fn offset_sn(&self, offset: f64) -> f64 {
match *self {
Cardinal::S => -offset,
Cardinal::N => offset,
_ => 0f64,
}
}
pub(super) fn offset_we(&self, offset: f64) -> f64 {
match *self {
Cardinal::W => -offset,
Cardinal::E => offset,
_ => 0f64,
}
}
#[allow(dead_code)]
pub(super) fn next_clockwise(&self) -> Cardinal {
match *self {
Cardinal::S => Cardinal::W,
Cardinal::E => Cardinal::S,
Cardinal::N => Cardinal::E,
Cardinal::W => Cardinal::N,
}
}
#[allow(dead_code)]
pub(super) fn next_counter_clockwise(&self) -> Cardinal {
match *self {
Cardinal::S => Cardinal::E,
Cardinal::E => Cardinal::N,
Cardinal::N => Cardinal::W,
Cardinal::W => Cardinal::S,
}
}
pub(super) fn clockwise_cycle(&self) -> (Cardinal, Cardinal, Cardinal, Cardinal) {
match *self {
Cardinal::S => (Cardinal::S, Cardinal::W, Cardinal::N, Cardinal::E),
Cardinal::E => (Cardinal::E, Cardinal::S, Cardinal::W, Cardinal::N),
Cardinal::N => (Cardinal::N, Cardinal::E, Cardinal::S, Cardinal::W),
Cardinal::W => (Cardinal::W, Cardinal::N, Cardinal::E, Cardinal::S),
}
}
pub(super) fn counter_clockwise_cycle(&self) -> (Cardinal, Cardinal, Cardinal, Cardinal) {
match *self {
Cardinal::S => (Cardinal::S, Cardinal::E, Cardinal::N, Cardinal::W),
Cardinal::E => (Cardinal::E, Cardinal::N, Cardinal::W, Cardinal::S),
Cardinal::N => (Cardinal::N, Cardinal::W, Cardinal::S, Cardinal::E),
Cardinal::W => (Cardinal::W, Cardinal::S, Cardinal::E, Cardinal::N),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct CardinalSet {
byte: u8,
}
impl Default for CardinalSet {
fn default() -> Self {
Self::new()
}
}
impl CardinalSet {
pub fn new() -> CardinalSet {
CardinalSet { byte: 0_u8 }
}
pub fn is_empty(&self) -> bool {
self.byte == 0
}
pub fn all() -> CardinalSet {
CardinalSet {
byte: 0b00001111_u8,
}
}
pub fn set(&mut self, key: Cardinal, value: bool) {
let i = key.index();
let mask = 1u8 << i;
if value {
self.byte |= mask;
} else {
self.byte &= !mask;
}
}
pub fn get(&self, key: Cardinal) -> bool {
let i = key.index();
self.get_from_index(i)
}
fn get_from_index(&self, index: u8) -> bool {
let mask = 1u8 << index;
self.byte & mask != 0u8
}
pub fn clear(&mut self) {
self.byte = 0u8;
}
}
impl IntoIterator for CardinalSet {
type Item = Cardinal;
type IntoIter = CardinalSetIterator;
fn into_iter(self) -> Self::IntoIter {
CardinalSetIterator {
cardinal_set: self,
index: 0,
}
}
}
pub struct CardinalSetIterator {
cardinal_set: CardinalSet,
index: u8,
}
impl Iterator for CardinalSetIterator {
type Item = Cardinal;
fn next(&mut self) -> Option<Cardinal> {
while self.index < 4 {
if self.cardinal_set.get_from_index(self.index) {
let card = Cardinal::from_index(self.index);
self.index += 1;
return Some(card);
} else {
self.index += 1;
}
}
None
}
}
pub struct CardinalMap<T: Copy> {
array: [Option<T>; 4],
}
impl<T: Copy> Default for CardinalMap<T> {
fn default() -> Self {
Self::new()
}
}
impl<V: Copy> CardinalMap<V> {
pub fn new() -> CardinalMap<V> {
CardinalMap {
array: [Option::None; 4],
}
}
pub fn put(&mut self, key: Cardinal, value: V) -> Option<V> {
mem::replace(&mut self.array[key.index() as usize], Some(value))
}
pub fn get(&self, key: Cardinal) -> Option<&V> {
self.array[key.index() as usize].as_ref()
}
pub fn clear(&mut self) {
for i in 0..4 {
self.array[i] = None;
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Ordinal {
SE = 0,
SW = 1,
NE = 2,
NW = 3,
}
impl Ordinal {
pub(crate) fn index(&self) -> u8 {
(*self) as u8
}
pub fn from_index(i: u8) -> Ordinal {
match i {
0 => Ordinal::SE,
1 => Ordinal::SW,
2 => Ordinal::NE,
3 => Ordinal::NW,
_ => panic!(
"Wrong Cardinal index: Expected value in [0, 3]; Actual value {}.",
i
),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct OrdinalSet {
byte: u8,
}
impl Default for OrdinalSet {
fn default() -> Self {
Self::new()
}
}
impl OrdinalSet {
pub fn new() -> Self {
OrdinalSet { byte: 0 }
}
pub fn is_empty(&self) -> bool {
self.byte == 0
}
pub fn all() -> OrdinalSet {
OrdinalSet {
byte: 0b00001111_u8,
}
}
pub fn set(&mut self, key: Ordinal, value: bool) {
let mask = 1u8 << key.index();
if value {
self.byte |= mask;
} else {
self.byte &= !mask;
}
}
pub fn get(&self, key: Ordinal) -> bool {
self.get_from_index(key.index())
}
fn get_from_index(&self, index: u8) -> bool {
let mask = 1u8 << index;
self.byte & mask != 0u8
}
pub fn clear(&mut self) {
self.byte = 0_u8;
}
}
impl IntoIterator for OrdinalSet {
type Item = Ordinal;
type IntoIter = OrdinalSetIterator;
fn into_iter(self) -> Self::IntoIter {
OrdinalSetIterator {
cardinal_set: self,
index: 0,
}
}
}
pub struct OrdinalSetIterator {
cardinal_set: OrdinalSet,
index: u8,
}
impl Iterator for OrdinalSetIterator {
type Item = Ordinal;
fn next(&mut self) -> Option<Ordinal> {
while self.index < 4 {
if self.cardinal_set.get_from_index(self.index) {
let ordinal = Ordinal::from_index(self.index);
self.index += 1;
return Some(ordinal);
} else {
self.index += 1;
}
}
None
}
}
pub struct OrdinalMap<T: Copy> {
array: [Option<T>; 4],
}
impl<T: Copy> Default for OrdinalMap<T> {
fn default() -> Self {
Self::new()
}
}
impl<V: Copy> OrdinalMap<V> {
pub fn new() -> OrdinalMap<V> {
OrdinalMap {
array: [Option::None; 4],
}
}
pub fn put(&mut self, key: Ordinal, value: V) -> Option<V> {
mem::replace(&mut self.array[key.index() as usize], Some(value))
}
pub fn get(&self, key: Ordinal) -> Option<&V> {
self.array[key.index() as usize].as_ref()
}
pub fn clear(&mut self) {
for i in 0..4 {
self.array[i] = None;
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum MainWind {
S,
SE,
E,
SW,
C,
NE,
W,
NW,
N,
}
impl MainWind {
pub fn from_index(i: u8) -> MainWind {
match i {
0 => MainWind::S,
1 => MainWind::SE,
2 => MainWind::E,
3 => MainWind::SW,
4 => MainWind::C,
5 => MainWind::NE,
6 => MainWind::W,
7 => MainWind::NW,
8 => MainWind::N,
_ => panic!(
"Wrong MainWind index: Expected value in [0, 7]; Actual value {}.",
i
),
}
}
pub fn is_cardinal(&self) -> bool {
matches!(*self, MainWind::S | MainWind::E | MainWind::N | MainWind::W)
}
pub fn to_cardinal(&self) -> Cardinal {
match *self {
MainWind::S => Cardinal::S,
MainWind::E => Cardinal::E,
MainWind::N => Cardinal::N,
MainWind::W => Cardinal::W,
_ => panic!("Main wind '{:?}' can't be converted to cardinal!", &self),
}
}
pub fn is_ordinal(&self) -> bool {
matches!(
*self,
MainWind::SE | MainWind::SW | MainWind::NE | MainWind::NW
)
}
pub fn to_ordinal(&self) -> Ordinal {
match *self {
MainWind::SE => Ordinal::SE,
MainWind::SW => Ordinal::SW,
MainWind::NE => Ordinal::NE,
MainWind::NW => Ordinal::NW,
_ => panic!("Main wind '{:?}' can't be converted to ordinal!", &self),
}
}
pub fn opposite(&self) -> MainWind {
match *self {
MainWind::S => MainWind::N,
MainWind::SE => MainWind::NW,
MainWind::E => MainWind::W,
MainWind::SW => MainWind::NE,
MainWind::C => MainWind::C,
MainWind::NE => MainWind::SW,
MainWind::W => MainWind::E,
MainWind::NW => MainWind::SE,
MainWind::N => MainWind::S,
}
}
pub fn from_offsets(offset_se: i8, offset_sw: i8) -> MainWind {
debug_assert!((-1_i8..=1_i8).contains(&offset_se));
debug_assert!((-1_i8..=1_i8).contains(&offset_sw));
let mut i = (offset_sw + 1_i8) as u8;
i += (i << 1) + (offset_se + 1_i8) as u8;
MainWind::from_index(i)
}
fn index(&self) -> u8 {
match *self {
MainWind::S => 0,
MainWind::SE => 1,
MainWind::E => 2,
MainWind::SW => 3,
MainWind::C => 4,
MainWind::NE => 5,
MainWind::W => 6,
MainWind::NW => 7,
MainWind::N => 8,
}
}
pub(super) fn offset_se(&self) -> i8 {
match *self {
MainWind::S => -1,
MainWind::SE => 0,
MainWind::E => 1,
MainWind::SW => -1,
MainWind::C => 0,
MainWind::NE => 1,
MainWind::W => -1,
MainWind::NW => 0,
MainWind::N => 1,
}
}
pub(super) fn offset_sw(&self) -> i8 {
match *self {
MainWind::S => -1,
MainWind::SE => -1,
MainWind::E => -1,
MainWind::SW => 0,
MainWind::C => 0,
MainWind::NE => 0,
MainWind::W => 1,
MainWind::NW => 1,
MainWind::N => 1,
}
}
}
#[derive(Debug)]
pub struct MainWindMap<T: Copy> {
array: [Option<T>; 9],
}
impl<T: Copy> Default for MainWindMap<T> {
fn default() -> Self {
Self::new()
}
}
impl<V: Copy> MainWindMap<V> {
pub fn new() -> MainWindMap<V> {
MainWindMap {
array: [Option::None; 9],
}
}
pub fn put(&mut self, key: MainWind, value: V) -> Option<V> {
mem::replace(&mut self.array[key.index() as usize], Some(value))
}
pub fn put_none(&mut self, key: MainWind) -> Option<V> {
self.array[key.index() as usize].take()
}
pub fn put_opt(&mut self, key: MainWind, value: Option<V>) -> Option<V> {
mem::replace(&mut self.array[key.index() as usize], value)
}
pub fn get(&self, key: MainWind) -> Option<&V> {
self.get_from_index(key.index() as usize)
}
fn get_from_index(&self, index: usize) -> Option<&V> {
self.array[index].as_ref()
}
pub fn clear(&self) {
let mut a = self.array;
fill_with_none(&mut a);
}
pub fn values_vec(&self) -> Vec<V> {
self.array.iter().filter_map(|&o| o).collect::<Vec<V>>()
}
pub fn entries(&self) -> Box<[(MainWind, V)]> {
self.entries_vec().into_boxed_slice()
}
pub fn entries_vec(&self) -> Vec<(MainWind, V)> {
self
.array
.iter()
.enumerate()
.filter_map(|(i, &o)| o.map(|v| (MainWind::from_index(i as u8), v)))
.collect::<Vec<(MainWind, V)>>()
}
}
impl<V: Copy + Ord> MainWindMap<V> {
pub fn sorted_values(&self) -> Box<[V]> {
self.sorted_values_vec().into_boxed_slice()
}
pub fn sorted_values_vec(&self) -> Vec<V> {
let mut values: Vec<V> = self.values_vec();
values.sort_unstable();
values
}
pub fn sorted_entries(&self) -> Box<[(MainWind, V)]> {
self.sorted_entries_vec().into_boxed_slice()
}
pub fn sorted_entries_vec(&self) -> Vec<(MainWind, V)> {
let mut entries = self.entries_vec();
entries.sort_unstable_by(|(_, v1), (_, v2)| v1.partial_cmp(v2).unwrap());
entries
}
}
fn fill_with_none<T>(array_of_option: &mut [Option<T>]) {
array_of_option.iter_mut().for_each(|o| *o = None);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testok_cardinal_index() {
assert_eq!(Cardinal::S as u8, 0_u8);
assert_eq!(Cardinal::E as u8, 1_u8);
assert_eq!(Cardinal::N as u8, 2_u8);
assert_eq!(Cardinal::W as u8, 3_u8);
assert_eq!(Cardinal::S.index(), 0_u8);
assert_eq!(Cardinal::E.index(), 1_u8);
assert_eq!(Cardinal::N.index(), 2_u8);
assert_eq!(Cardinal::W.index(), 3_u8);
}
#[test]
fn testok_cardinal_fromindex() {
assert_eq!(Cardinal::S, Cardinal::from_index(0_u8));
assert_eq!(Cardinal::E, Cardinal::from_index(1_u8));
assert_eq!(Cardinal::N, Cardinal::from_index(2_u8));
assert_eq!(Cardinal::W, Cardinal::from_index(3_u8));
}
#[test]
fn testok_ordinalset() {
let os = OrdinalSet::all();
let mut it = os.into_iter();
assert_eq!(it.next(), Some(Ordinal::from_index(0)));
assert_eq!(it.next(), Some(Ordinal::from_index(1)));
assert_eq!(it.next(), Some(Ordinal::from_index(2)));
assert_eq!(it.next(), Some(Ordinal::from_index(3)));
assert_eq!(it.next(), None);
let os = OrdinalSet::default();
let mut it = os.into_iter();
assert_eq!(it.next(), None);
let mut os = OrdinalSet::default();
os.set(Ordinal::NE, true);
os.set(Ordinal::NW, true);
let mut it = os.into_iter();
assert_eq!(it.next(), Some(Ordinal::NE));
assert_eq!(it.next(), Some(Ordinal::NW));
assert_eq!(it.next(), None);
}
}