use std::cmp::Ordering;
use std::fmt;
use std::iter::Sum;
use std::marker::PhantomData;
use std::ops::{Add, AddAssign, Div, Mul, Neg, Range, Rem, Sub, SubAssign};
#[derive(Copy, Clone, Debug, Ord, Eq)]
pub struct AxisIndex<T: AxisDimension> {
val: i32,
_dim: PhantomData<T>,
}
impl<T: AxisDimension> AxisIndex<T> {
pub fn new(v: i32) -> Self {
AxisIndex {
val: v,
_dim: Default::default(),
}
}
pub fn raw_value(self) -> i32 {
self.into()
}
pub fn diff_to_origin(self) -> AxisDiff<T> {
AxisDiff::new(self.val)
}
pub fn positive_or_zero(self) -> AxisIndex<T> {
AxisIndex::new(self.val.max(0))
}
}
impl<T: AxisDimension> From<i32> for AxisIndex<T> {
fn from(v: i32) -> Self {
AxisIndex::new(v)
}
}
impl<T: AxisDimension> Into<i32> for AxisIndex<T> {
fn into(self) -> i32 {
self.val
}
}
impl<T: AxisDimension> Into<isize> for AxisIndex<T> {
fn into(self) -> isize {
self.val as isize
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> Add<I> for AxisIndex<T> {
type Output = Self;
fn add(self, rhs: I) -> Self {
AxisIndex::new(self.val + rhs.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> AddAssign<I> for AxisIndex<T> {
fn add_assign(&mut self, rhs: I) {
*self = *self + rhs;
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> Sub<I> for AxisIndex<T> {
type Output = Self;
fn sub(self, rhs: I) -> Self {
AxisIndex::new(self.val - rhs.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> SubAssign<I> for AxisIndex<T> {
fn sub_assign(&mut self, rhs: I) {
*self = *self - rhs;
}
}
impl<T: AxisDimension> Sub<Self> for AxisIndex<T> {
type Output = AxisDiff<T>;
fn sub(self, rhs: Self) -> Self::Output {
AxisDiff::new(self.val - rhs.val)
}
}
impl<T: AxisDimension, I: Into<AxisIndex<T>>> Rem<I> for AxisIndex<T> {
type Output = Self;
fn rem(self, modulus: I) -> Self {
Self::new(self.val % modulus.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisIndex<T>> + Copy> PartialEq<I> for AxisIndex<T> {
fn eq(&self, other: &I) -> bool {
let copy = *other;
self.val == copy.into().val
}
}
impl<T: AxisDimension, I: Into<AxisIndex<T>> + Copy> PartialOrd<I> for AxisIndex<T> {
fn partial_cmp(&self, other: &I) -> Option<Ordering> {
let copy = *other;
Some(self.val.cmp(©.into().val))
}
}
impl<T: AxisDimension> Neg for AxisIndex<T> {
type Output = Self;
fn neg(self) -> Self::Output {
AxisIndex::new(-self.val)
}
}
pub struct IndexRange<T: AxisDimension>(pub Range<AxisIndex<T>>);
impl<T: AxisDimension> Iterator for IndexRange<T> {
type Item = AxisIndex<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.0.start < self.0.end {
let res = self.0.start;
self.0.start += 1;
Some(res)
} else {
None
}
}
}
#[derive(Copy, Clone, Debug, Ord, Eq)]
pub struct AxisDiff<T: AxisDimension> {
val: i32,
_dim: PhantomData<T>,
}
impl<T: AxisDimension> AxisDiff<T> {
pub fn new(v: i32) -> Self {
AxisDiff {
val: v,
_dim: Default::default(),
}
}
pub fn raw_value(self) -> i32 {
self.into()
}
pub fn from_origin(self) -> AxisIndex<T> {
AxisIndex::new(self.val)
}
pub fn try_into_positive(self) -> Result<PositiveAxisDiff<T>, Self> {
PositiveAxisDiff::new(self.val).map_err(|()| self)
}
pub fn abs(self) -> PositiveAxisDiff<T> {
PositiveAxisDiff::new_unchecked(self.val.abs())
}
pub fn positive_or_zero(self) -> PositiveAxisDiff<T> {
PositiveAxisDiff::new_unchecked(self.val.max(0))
}
}
impl<T: AxisDimension> From<i32> for AxisDiff<T> {
fn from(v: i32) -> Self {
AxisDiff::new(v)
}
}
impl<T: AxisDimension> Into<i32> for AxisDiff<T> {
fn into(self) -> i32 {
self.val
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> Add<I> for AxisDiff<T> {
type Output = Self;
fn add(self, rhs: I) -> Self {
AxisDiff::new(self.val + rhs.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> AddAssign<I> for AxisDiff<T> {
fn add_assign(&mut self, rhs: I) {
*self = *self + rhs;
}
}
impl<T: AxisDimension> Mul<i32> for AxisDiff<T> {
type Output = Self;
fn mul(self, rhs: i32) -> Self::Output {
AxisDiff::new(self.val * rhs)
}
}
impl<T: AxisDimension> Div<i32> for AxisDiff<T> {
type Output = AxisDiff<T>;
fn div(self, rhs: i32) -> Self::Output {
AxisDiff::new(self.val / rhs)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> Sub<I> for AxisDiff<T> {
type Output = Self;
fn sub(self, rhs: I) -> Self {
AxisDiff::new(self.val - rhs.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> SubAssign<I> for AxisDiff<T> {
fn sub_assign(&mut self, rhs: I) {
*self = *self - rhs;
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> Rem<I> for AxisDiff<T> {
type Output = Self;
fn rem(self, modulus: I) -> Self {
AxisDiff::new(self.val % modulus.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>> + Copy> PartialEq<I> for AxisDiff<T> {
fn eq(&self, other: &I) -> bool {
let copy = *other;
self.val == copy.into().val
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>> + Copy> PartialOrd<I> for AxisDiff<T> {
fn partial_cmp(&self, other: &I) -> Option<Ordering> {
let copy = *other;
Some(self.val.cmp(©.into().val))
}
}
impl<T: AxisDimension> Neg for AxisDiff<T> {
type Output = Self;
fn neg(self) -> Self::Output {
AxisDiff::new(-self.val)
}
}
#[derive(Copy, Clone, Debug, Ord, Eq)]
pub struct PositiveAxisDiff<T: AxisDimension> {
val: i32,
_dim: PhantomData<T>,
}
impl<T: AxisDimension> PositiveAxisDiff<T> {
pub fn new_unchecked(v: i32) -> Self {
assert!(v >= 0, "Invalid value for PositiveAxisDiff");
PositiveAxisDiff {
val: v,
_dim: Default::default(),
}
}
pub fn new(v: i32) -> Result<Self, ()> {
if v >= 0 {
Ok(PositiveAxisDiff {
val: v,
_dim: Default::default(),
})
} else {
Err(())
}
}
pub fn raw_value(self) -> i32 {
self.into()
}
pub fn from_origin(self) -> AxisIndex<T> {
AxisIndex::new(self.val)
}
pub fn origin_range_contains(self, i: AxisIndex<T>) -> bool {
0 <= i.val && i.val < self.val
}
pub fn to_signed(self) -> AxisDiff<T> {
AxisDiff::new(self.val)
}
}
impl<T: AxisDimension> Into<i32> for PositiveAxisDiff<T> {
fn into(self) -> i32 {
self.val
}
}
impl<T: AxisDimension> Into<usize> for PositiveAxisDiff<T> {
fn into(self) -> usize {
self.val as usize
}
}
impl<T: AxisDimension> Into<AxisDiff<T>> for PositiveAxisDiff<T> {
fn into(self) -> AxisDiff<T> {
AxisDiff::new(self.val)
}
}
impl<T: AxisDimension, I: Into<PositiveAxisDiff<T>>> Add<I> for PositiveAxisDiff<T> {
type Output = Self;
fn add(self, rhs: I) -> Self {
PositiveAxisDiff::new_unchecked(self.val + rhs.into().val)
}
}
impl<T: AxisDimension, I: Into<PositiveAxisDiff<T>>> AddAssign<I> for PositiveAxisDiff<T> {
fn add_assign(&mut self, rhs: I) {
*self = *self + rhs;
}
}
impl<T: AxisDimension> Mul<i32> for PositiveAxisDiff<T> {
type Output = AxisDiff<T>;
fn mul(self, rhs: i32) -> Self::Output {
AxisDiff::new(self.val * rhs)
}
}
impl<T: AxisDimension> Mul<usize> for PositiveAxisDiff<T> {
type Output = Self;
fn mul(self, rhs: usize) -> Self::Output {
PositiveAxisDiff::new_unchecked(self.val * rhs as i32)
}
}
impl<T: AxisDimension> Div<i32> for PositiveAxisDiff<T> {
type Output = AxisDiff<T>;
fn div(self, rhs: i32) -> Self::Output {
AxisDiff::new(self.val / rhs)
}
}
impl<T: AxisDimension> Div<usize> for PositiveAxisDiff<T> {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
PositiveAxisDiff::new_unchecked(self.val / rhs as i32)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>>> Sub<I> for PositiveAxisDiff<T> {
type Output = AxisDiff<T>;
fn sub(self, rhs: I) -> Self::Output {
AxisDiff::new(self.val - rhs.into().val)
}
}
impl<T: AxisDimension, I: Into<PositiveAxisDiff<T>>> Rem<I> for PositiveAxisDiff<T> {
type Output = Self;
fn rem(self, modulus: I) -> Self {
PositiveAxisDiff::new_unchecked(self.val % modulus.into().val)
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>> + Copy> PartialEq<I> for PositiveAxisDiff<T> {
fn eq(&self, other: &I) -> bool {
let copy = *other;
self.val == copy.into().val
}
}
impl<T: AxisDimension, I: Into<AxisDiff<T>> + Copy> PartialOrd<I> for PositiveAxisDiff<T> {
fn partial_cmp(&self, other: &I) -> Option<Ordering> {
let copy = *other;
Some(self.val.cmp(©.into().val))
}
}
impl<T: AxisDimension + PartialOrd + Ord> Sum for PositiveAxisDiff<T> {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(PositiveAxisDiff::new_unchecked(0), PositiveAxisDiff::add)
}
}
impl<T: AxisDimension> From<usize> for PositiveAxisDiff<T> {
fn from(v: usize) -> Self {
assert!(
v < i32::max_value() as usize,
"Invalid PositiveAxisDiff value"
);
PositiveAxisDiff::new_unchecked(v as i32)
}
}
pub trait AxisDimension: Copy {
const NDARRAY_AXIS_NUMBER: usize;
fn get_dimension_value(val: (usize, usize)) -> usize;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ColDimension;
impl AxisDimension for ColDimension {
const NDARRAY_AXIS_NUMBER: usize = 1;
fn get_dimension_value(val: (usize, usize)) -> usize {
val.1
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct RowDimension;
impl AxisDimension for RowDimension {
const NDARRAY_AXIS_NUMBER: usize = 0;
fn get_dimension_value(val: (usize, usize)) -> usize {
val.0
}
}
pub type ColIndex = AxisIndex<ColDimension>;
pub type ColDiff = AxisDiff<ColDimension>;
pub type Width = PositiveAxisDiff<ColDimension>;
pub type RowIndex = AxisIndex<RowDimension>;
pub type RowDiff = AxisDiff<RowDimension>;
pub type Height = PositiveAxisDiff<RowDimension>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug, Hash)]
pub struct LineIndex(usize);
impl LineIndex {
pub fn new(val: usize) -> Self {
LineIndex(val)
}
pub fn raw_value(self) -> usize {
self.0
}
pub fn checked_sub(&self, rhs: usize) -> Option<LineIndex> {
let index = self.0;
index.checked_sub(rhs).map(LineIndex)
}
}
impl Into<usize> for LineIndex {
fn into(self) -> usize {
let LineIndex(index) = self;
index
}
}
impl From<LineNumber> for LineIndex {
fn from(LineNumber(raw_number): LineNumber) -> Self {
LineIndex::new(raw_number - 1)
}
}
impl Add<usize> for LineIndex {
type Output = Self;
fn add(self, rhs: usize) -> Self {
let raw_index: usize = self.into();
LineIndex::new(raw_index + rhs)
}
}
impl AddAssign<usize> for LineIndex {
fn add_assign(&mut self, rhs: usize) {
*self = *self + rhs;
}
}
impl Sub<usize> for LineIndex {
type Output = Self;
fn sub(self, rhs: usize) -> Self {
let raw_index: usize = self.into();
LineIndex::new(raw_index - rhs)
}
}
impl SubAssign<usize> for LineIndex {
fn sub_assign(&mut self, rhs: usize) {
*self = *self - rhs;
}
}
impl fmt::Display for LineIndex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug, Hash)]
pub struct LineNumber(usize);
impl LineNumber {
pub fn new(val: usize) -> Self {
assert!(val > 0, "Invalid LineNumber: Number == 0");
LineNumber(val)
}
pub fn raw_value(self) -> usize {
self.0
}
pub fn checked_sub(&self, rhs: usize) -> Option<LineNumber> {
let index = self.0 - 1;
index.checked_sub(rhs).map(|i| LineNumber(i + 1))
}
}
impl Into<usize> for LineNumber {
fn into(self) -> usize {
self.0
}
}
impl From<LineIndex> for LineNumber {
fn from(LineIndex(raw_index): LineIndex) -> Self {
LineNumber::new(raw_index + 1)
}
}
impl Add<usize> for LineNumber {
type Output = Self;
fn add(self, rhs: usize) -> Self {
let raw_number: usize = self.into();
LineNumber::new(raw_number + rhs)
}
}
impl AddAssign<usize> for LineNumber {
fn add_assign(&mut self, rhs: usize) {
*self = *self + rhs;
}
}
impl Sub<usize> for LineNumber {
type Output = Self;
fn sub(self, rhs: usize) -> Self {
let raw_number: usize = self.into();
LineNumber::new(raw_number - rhs)
}
}
impl SubAssign<usize> for LineNumber {
fn sub_assign(&mut self, rhs: usize) {
*self = *self - rhs;
}
}
impl fmt::Display for LineNumber {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}