2020-05-05 22:50:23 +00:00
|
|
|
//! Line and Column newtypes for strongly typed tty/grid/terminal APIs.
|
2016-07-04 04:05:28 +00:00
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// Indexing types and implementations for Grid and Line.
|
2016-12-22 18:43:06 +00:00
|
|
|
use std::cmp::{Ord, Ordering};
|
2016-07-04 04:05:28 +00:00
|
|
|
use std::fmt;
|
2019-11-03 20:59:28 +00:00
|
|
|
use std::ops::{self, Add, AddAssign, Deref, Range, Sub, SubAssign};
|
2019-03-19 19:14:17 +00:00
|
|
|
|
2019-10-05 00:29:26 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
use crate::grid::Dimensions;
|
2019-04-19 12:07:56 +00:00
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// The side of a cell.
|
2020-07-09 21:45:22 +00:00
|
|
|
pub type Side = Direction;
|
|
|
|
|
|
|
|
/// Horizontal direction.
|
2016-12-22 18:43:06 +00:00
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
2020-07-09 21:45:22 +00:00
|
|
|
pub enum Direction {
|
2016-12-22 18:43:06 +00:00
|
|
|
Left,
|
2019-03-30 16:48:36 +00:00
|
|
|
Right,
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
impl Direction {
|
2020-03-18 02:35:08 +00:00
|
|
|
pub fn opposite(self) -> Self {
|
|
|
|
match self {
|
|
|
|
Side::Right => Side::Left,
|
|
|
|
Side::Left => Side::Right,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
/// Behavior for handling grid boundaries.
|
|
|
|
pub enum Boundary {
|
|
|
|
/// Clamp to grid boundaries.
|
|
|
|
///
|
|
|
|
/// When an operation exceeds the grid boundaries, the last point will be returned no matter
|
|
|
|
/// how far the boundaries were exceeded.
|
|
|
|
Clamp,
|
|
|
|
|
|
|
|
/// Wrap around grid bondaries.
|
|
|
|
///
|
|
|
|
/// When an operation exceeds the grid boundaries, the point will wrap around the entire grid
|
|
|
|
/// history and continue at the other side.
|
|
|
|
Wrap,
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// Index in the grid using row, column notation.
|
2020-12-31 05:52:45 +00:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Default, Eq, PartialEq)]
|
2019-03-30 16:48:36 +00:00
|
|
|
pub struct Point<L = Line> {
|
2018-03-07 04:57:40 +00:00
|
|
|
pub line: L,
|
2021-01-24 21:45:36 +00:00
|
|
|
pub column: Column,
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|
|
|
|
|
2018-03-07 04:57:40 +00:00
|
|
|
impl<L> Point<L> {
|
|
|
|
pub fn new(line: L, col: Column) -> Point<L> {
|
2021-01-24 21:45:36 +00:00
|
|
|
Point { line, column: col }
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|
2019-11-03 20:59:28 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
2020-05-30 20:45:44 +00:00
|
|
|
pub fn sub(mut self, num_cols: Column, rhs: usize) -> Point<L>
|
2019-11-03 20:59:28 +00:00
|
|
|
where
|
2020-02-07 06:50:18 +00:00
|
|
|
L: Copy + Default + Into<Line> + Add<usize, Output = L> + Sub<usize, Output = L>,
|
2019-11-03 20:59:28 +00:00
|
|
|
{
|
2020-05-30 20:45:44 +00:00
|
|
|
let num_cols = num_cols.0;
|
2021-01-24 21:45:36 +00:00
|
|
|
let line_changes = (rhs + num_cols - 1).saturating_sub(self.column.0) / num_cols;
|
2020-05-30 20:45:44 +00:00
|
|
|
if self.line.into() >= Line(line_changes) {
|
2020-02-07 06:50:18 +00:00
|
|
|
self.line = self.line - line_changes;
|
2021-01-24 21:45:36 +00:00
|
|
|
self.column = Column((num_cols + self.column.0 - rhs % num_cols) % num_cols);
|
2020-05-30 20:45:44 +00:00
|
|
|
self
|
2020-01-09 23:06:41 +00:00
|
|
|
} else {
|
2020-05-30 20:45:44 +00:00
|
|
|
Point::new(L::default(), Column(0))
|
2020-01-09 23:06:41 +00:00
|
|
|
}
|
2019-11-03 20:59:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
2020-05-30 20:45:44 +00:00
|
|
|
pub fn add(mut self, num_cols: Column, rhs: usize) -> Point<L>
|
2019-11-03 20:59:28 +00:00
|
|
|
where
|
2020-03-18 02:35:08 +00:00
|
|
|
L: Copy + Default + Into<Line> + Add<usize, Output = L> + Sub<usize, Output = L>,
|
2019-11-03 20:59:28 +00:00
|
|
|
{
|
2020-05-30 20:45:44 +00:00
|
|
|
let num_cols = num_cols.0;
|
2021-01-24 21:45:36 +00:00
|
|
|
self.line = self.line + (rhs + self.column.0) / num_cols;
|
|
|
|
self.column = Column((self.column.0 + rhs) % num_cols);
|
2019-11-03 20:59:28 +00:00
|
|
|
self
|
|
|
|
}
|
2020-07-09 21:45:22 +00:00
|
|
|
}
|
2020-03-18 02:35:08 +00:00
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
impl Point<usize> {
|
2020-03-18 02:35:08 +00:00
|
|
|
#[inline]
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
2020-07-09 21:45:22 +00:00
|
|
|
pub fn sub_absolute<D>(mut self, dimensions: &D, boundary: Boundary, rhs: usize) -> Point<usize>
|
2020-03-18 02:35:08 +00:00
|
|
|
where
|
2020-07-09 21:45:22 +00:00
|
|
|
D: Dimensions,
|
2020-03-18 02:35:08 +00:00
|
|
|
{
|
2020-07-09 21:45:22 +00:00
|
|
|
let total_lines = dimensions.total_lines();
|
|
|
|
let num_cols = dimensions.cols().0;
|
|
|
|
|
2021-01-24 21:45:36 +00:00
|
|
|
self.line += (rhs + num_cols - 1).saturating_sub(self.column.0) / num_cols;
|
|
|
|
self.column = Column((num_cols + self.column.0 - rhs % num_cols) % num_cols);
|
2020-07-09 21:45:22 +00:00
|
|
|
|
|
|
|
if self.line >= total_lines {
|
|
|
|
match boundary {
|
|
|
|
Boundary::Clamp => Point::new(total_lines - 1, Column(0)),
|
2021-01-24 21:45:36 +00:00
|
|
|
Boundary::Wrap => Point::new(self.line - total_lines, self.column),
|
2020-07-09 21:45:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self
|
|
|
|
}
|
2020-03-18 02:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
2020-07-09 21:45:22 +00:00
|
|
|
pub fn add_absolute<D>(mut self, dimensions: &D, boundary: Boundary, rhs: usize) -> Point<usize>
|
2020-03-18 02:35:08 +00:00
|
|
|
where
|
2020-07-09 21:45:22 +00:00
|
|
|
D: Dimensions,
|
2020-03-18 02:35:08 +00:00
|
|
|
{
|
2020-07-09 21:45:22 +00:00
|
|
|
let num_cols = dimensions.cols();
|
|
|
|
|
2021-01-24 21:45:36 +00:00
|
|
|
let line_delta = (rhs + self.column.0) / num_cols.0;
|
2020-07-09 21:45:22 +00:00
|
|
|
|
|
|
|
if self.line >= line_delta {
|
|
|
|
self.line -= line_delta;
|
2021-01-24 21:45:36 +00:00
|
|
|
self.column = Column((self.column.0 + rhs) % num_cols.0);
|
2020-05-30 20:45:44 +00:00
|
|
|
self
|
2020-03-18 02:35:08 +00:00
|
|
|
} else {
|
2020-07-09 21:45:22 +00:00
|
|
|
match boundary {
|
|
|
|
Boundary::Clamp => Point::new(0, num_cols - 1),
|
|
|
|
Boundary::Wrap => {
|
2021-01-24 21:45:36 +00:00
|
|
|
let col = Column((self.column.0 + rhs) % num_cols.0);
|
2020-07-09 21:45:22 +00:00
|
|
|
let line = dimensions.total_lines() + self.line - line_delta;
|
|
|
|
Point::new(line, col)
|
|
|
|
},
|
|
|
|
}
|
2020-03-18 02:35:08 +00:00
|
|
|
}
|
|
|
|
}
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
impl PartialOrd for Point {
|
|
|
|
fn partial_cmp(&self, other: &Point) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-29 16:09:29 +00:00
|
|
|
impl Ord for Point {
|
|
|
|
fn cmp(&self, other: &Point) -> Ordering {
|
2021-01-24 21:45:36 +00:00
|
|
|
match (self.line.cmp(&other.line), self.column.cmp(&other.column)) {
|
2020-07-09 21:45:22 +00:00
|
|
|
(Ordering::Equal, ord) | (ord, _) => ord,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for Point<usize> {
|
|
|
|
fn partial_cmp(&self, other: &Point<usize>) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for Point<usize> {
|
|
|
|
fn cmp(&self, other: &Point<usize>) -> Ordering {
|
2021-01-24 21:45:36 +00:00
|
|
|
match (self.line.cmp(&other.line), self.column.cmp(&other.column)) {
|
2020-07-09 21:45:22 +00:00
|
|
|
(Ordering::Equal, ord) => ord,
|
|
|
|
(Ordering::Less, _) => Ordering::Greater,
|
|
|
|
(Ordering::Greater, _) => Ordering::Less,
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 22:30:59 +00:00
|
|
|
impl From<Point<usize>> for Point<isize> {
|
|
|
|
fn from(point: Point<usize>) -> Self {
|
2021-01-24 21:45:36 +00:00
|
|
|
Point::new(point.line as isize, point.column)
|
2018-10-20 22:30:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 15:37:01 +00:00
|
|
|
impl From<Point<usize>> for Point<Line> {
|
|
|
|
fn from(point: Point<usize>) -> Self {
|
2021-01-24 21:45:36 +00:00
|
|
|
Point::new(Line(point.line), point.column)
|
2019-08-01 15:37:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 22:30:59 +00:00
|
|
|
impl From<Point<isize>> for Point<usize> {
|
|
|
|
fn from(point: Point<isize>) -> Self {
|
2021-01-24 21:45:36 +00:00
|
|
|
Point::new(point.line as usize, point.column)
|
2018-10-20 22:30:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-22 19:39:26 +00:00
|
|
|
impl From<Point> for Point<usize> {
|
|
|
|
fn from(point: Point) -> Self {
|
2021-01-24 21:45:36 +00:00
|
|
|
Point::new(point.line.0, point.column)
|
2019-04-19 12:07:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// A line.
|
2016-07-04 04:05:28 +00:00
|
|
|
///
|
2020-05-05 22:50:23 +00:00
|
|
|
/// Newtype to avoid passing values incorrectly.
|
2020-12-31 05:52:45 +00:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd)]
|
2016-07-04 04:05:28 +00:00
|
|
|
pub struct Line(pub usize);
|
|
|
|
|
|
|
|
impl fmt::Display for Line {
|
2018-12-10 17:53:56 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2017-01-02 02:28:49 +00:00
|
|
|
write!(f, "{}", self.0)
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// A column.
|
2016-07-04 04:05:28 +00:00
|
|
|
///
|
2020-05-05 22:50:23 +00:00
|
|
|
/// Newtype to avoid passing values incorrectly.
|
2020-12-31 05:52:45 +00:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd)]
|
2016-07-04 04:05:28 +00:00
|
|
|
pub struct Column(pub usize);
|
|
|
|
|
|
|
|
impl fmt::Display for Column {
|
2018-12-10 17:53:56 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2017-01-02 02:28:49 +00:00
|
|
|
write!(f, "{}", self.0)
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-06 01:42:55 +00:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
//
|
|
|
|
// implements binary operators "&T op U", "T op &U", "&T op &U"
|
|
|
|
// based on "T op U" where T and U are expected to be `Copy`able
|
2016-07-04 04:05:28 +00:00
|
|
|
macro_rules! forward_ref_binop {
|
|
|
|
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
|
|
|
|
impl<'a> $imp<$u> for &'a $t {
|
|
|
|
type Output = <$t as $imp<$u>>::Output;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
|
|
|
|
$imp::$method(*self, other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> $imp<&'a $u> for $t {
|
|
|
|
type Output = <$t as $imp<$u>>::Output;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
|
|
|
|
$imp::$method(self, *other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> $imp<&'a $u> for &'b $t {
|
|
|
|
type Output = <$t as $imp<$u>>::Output;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
|
|
|
|
$imp::$method(*self, *other)
|
|
|
|
}
|
|
|
|
}
|
2019-03-30 16:48:36 +00:00
|
|
|
};
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// Macro for deriving deref.
|
2016-07-04 04:05:28 +00:00
|
|
|
macro_rules! deref {
|
|
|
|
($ty:ty, $target:ty) => {
|
|
|
|
impl Deref for $ty {
|
|
|
|
type Target = $target;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn deref(&self) -> &$target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
2019-03-30 16:48:36 +00:00
|
|
|
};
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! add {
|
|
|
|
($ty:ty, $construct:expr) => {
|
|
|
|
impl ops::Add<$ty> for $ty {
|
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add(self, rhs: $ty) -> $ty {
|
|
|
|
$construct(self.0 + rhs.0)
|
|
|
|
}
|
|
|
|
}
|
2019-03-30 16:48:36 +00:00
|
|
|
};
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! sub {
|
|
|
|
($ty:ty, $construct:expr) => {
|
|
|
|
impl ops::Sub<$ty> for $ty {
|
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, rhs: $ty) -> $ty {
|
|
|
|
$construct(self.0 - rhs.0)
|
|
|
|
}
|
|
|
|
}
|
2016-08-22 15:37:50 +00:00
|
|
|
|
|
|
|
impl<'a> ops::Sub<$ty> for &'a $ty {
|
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, rhs: $ty) -> $ty {
|
|
|
|
$construct(self.0 - rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ops::Sub<&'a $ty> for $ty {
|
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, rhs: &'a $ty) -> $ty {
|
|
|
|
$construct(self.0 - rhs.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> ops::Sub<&'a $ty> for &'b $ty {
|
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, rhs: &'a $ty) -> $ty {
|
|
|
|
$construct(self.0 - rhs.0)
|
|
|
|
}
|
|
|
|
}
|
2019-03-30 16:48:36 +00:00
|
|
|
};
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 23:25:04 +00:00
|
|
|
/// This exists because we can't implement Iterator on Range
|
|
|
|
/// and the existing impl needs the unstable Step trait
|
|
|
|
/// This should be removed and replaced with a Step impl
|
2020-05-05 22:50:23 +00:00
|
|
|
/// in the ops macro when `step_by` is stabilized.
|
2017-01-06 23:25:04 +00:00
|
|
|
pub struct IndexRange<T>(pub Range<T>);
|
|
|
|
|
|
|
|
impl<T> From<Range<T>> for IndexRange<T> {
|
|
|
|
fn from(from: Range<T>) -> Self {
|
|
|
|
IndexRange(from)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-04 04:05:28 +00:00
|
|
|
macro_rules! ops {
|
|
|
|
($ty:ty, $construct:expr) => {
|
|
|
|
add!($ty, $construct);
|
|
|
|
sub!($ty, $construct);
|
|
|
|
deref!($ty, usize);
|
|
|
|
forward_ref_binop!(impl Add, add for $ty, $ty);
|
|
|
|
|
2017-01-06 23:25:04 +00:00
|
|
|
impl $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
#[inline]
|
2018-07-21 17:17:41 +00:00
|
|
|
fn steps_between(start: $ty, end: $ty, by: $ty) -> Option<usize> {
|
|
|
|
if by == $construct(0) { return None; }
|
|
|
|
if start < end {
|
2020-05-05 22:50:23 +00:00
|
|
|
// Note: We assume $t <= usize here.
|
2018-07-21 17:17:41 +00:00
|
|
|
let diff = (end - start).0;
|
2016-07-04 04:05:28 +00:00
|
|
|
let by = by.0;
|
|
|
|
if diff % by > 0 {
|
|
|
|
Some(diff / by + 1)
|
|
|
|
} else {
|
|
|
|
Some(diff / by)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Some(0)
|
|
|
|
}
|
|
|
|
}
|
2016-07-15 14:55:44 +00:00
|
|
|
|
|
|
|
#[inline]
|
2018-07-21 17:17:41 +00:00
|
|
|
fn steps_between_by_one(start: $ty, end: $ty) -> Option<usize> {
|
|
|
|
Self::steps_between(start, end, $construct(1))
|
2016-07-15 14:55:44 +00:00
|
|
|
}
|
2017-01-06 23:25:04 +00:00
|
|
|
}
|
2016-07-15 14:55:44 +00:00
|
|
|
|
2017-01-06 23:25:04 +00:00
|
|
|
impl Iterator for IndexRange<$ty> {
|
|
|
|
type Item = $ty;
|
2016-07-15 14:55:44 +00:00
|
|
|
#[inline]
|
2017-01-06 23:25:04 +00:00
|
|
|
fn next(&mut self) -> Option<$ty> {
|
|
|
|
if self.0.start < self.0.end {
|
|
|
|
let old = self.0.start;
|
|
|
|
self.0.start = old + 1;
|
|
|
|
Some(old)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2016-07-15 14:55:44 +00:00
|
|
|
}
|
|
|
|
#[inline]
|
2017-01-06 23:25:04 +00:00
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
2018-07-21 17:17:41 +00:00
|
|
|
match Self::Item::steps_between_by_one(self.0.start, self.0.end) {
|
2017-01-06 23:25:04 +00:00
|
|
|
Some(hint) => (hint, Some(hint)),
|
|
|
|
None => (0, None)
|
|
|
|
}
|
2016-07-15 14:55:44 +00:00
|
|
|
}
|
2017-01-06 23:25:04 +00:00
|
|
|
}
|
2016-07-15 14:55:44 +00:00
|
|
|
|
2017-01-06 23:25:04 +00:00
|
|
|
impl DoubleEndedIterator for IndexRange<$ty> {
|
2016-07-15 14:55:44 +00:00
|
|
|
#[inline]
|
2017-01-06 23:25:04 +00:00
|
|
|
fn next_back(&mut self) -> Option<$ty> {
|
|
|
|
if self.0.start < self.0.end {
|
|
|
|
let new = self.0.end - 1;
|
|
|
|
self.0.end = new;
|
|
|
|
Some(new)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2016-07-15 14:55:44 +00:00
|
|
|
}
|
2016-07-04 04:05:28 +00:00
|
|
|
}
|
2019-03-19 19:14:17 +00:00
|
|
|
impl AddAssign<$ty> for $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
#[inline]
|
|
|
|
fn add_assign(&mut self, rhs: $ty) {
|
|
|
|
self.0 += rhs.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 19:14:17 +00:00
|
|
|
impl SubAssign<$ty> for $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
#[inline]
|
|
|
|
fn sub_assign(&mut self, rhs: $ty) {
|
|
|
|
self.0 -= rhs.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 19:14:17 +00:00
|
|
|
impl AddAssign<usize> for $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
#[inline]
|
|
|
|
fn add_assign(&mut self, rhs: usize) {
|
|
|
|
self.0 += rhs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 19:14:17 +00:00
|
|
|
impl SubAssign<usize> for $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
#[inline]
|
|
|
|
fn sub_assign(&mut self, rhs: usize) {
|
|
|
|
self.0 -= rhs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<usize> for $ty {
|
|
|
|
#[inline]
|
|
|
|
fn from(val: usize) -> $ty {
|
|
|
|
$construct(val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 19:14:17 +00:00
|
|
|
impl Add<usize> for $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add(self, rhs: usize) -> $ty {
|
|
|
|
$construct(self.0 + rhs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-19 19:14:17 +00:00
|
|
|
impl Sub<usize> for $ty {
|
2016-07-04 04:05:28 +00:00
|
|
|
type Output = $ty;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, rhs: usize) -> $ty {
|
|
|
|
$construct(self.0 - rhs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ops!(Line, Line);
|
|
|
|
ops!(Column, Column);
|
2016-12-22 18:43:06 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2020-07-09 21:45:22 +00:00
|
|
|
use super::*;
|
2016-12-22 18:43:06 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn location_ordering() {
|
2016-12-29 16:09:29 +00:00
|
|
|
assert!(Point::new(Line(0), Column(0)) == Point::new(Line(0), Column(0)));
|
|
|
|
assert!(Point::new(Line(1), Column(0)) > Point::new(Line(0), Column(0)));
|
|
|
|
assert!(Point::new(Line(0), Column(1)) > Point::new(Line(0), Column(0)));
|
|
|
|
assert!(Point::new(Line(1), Column(1)) > Point::new(Line(0), Column(0)));
|
|
|
|
assert!(Point::new(Line(1), Column(1)) > Point::new(Line(0), Column(1)));
|
|
|
|
assert!(Point::new(Line(1), Column(1)) > Point::new(Line(1), Column(0)));
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|
2020-05-30 20:45:44 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub() {
|
|
|
|
let num_cols = Column(42);
|
|
|
|
let point = Point::new(0, Column(13));
|
|
|
|
|
|
|
|
let result = point.sub(num_cols, 1);
|
|
|
|
|
2021-01-24 21:45:36 +00:00
|
|
|
assert_eq!(result, Point::new(0, point.column - 1));
|
2020-05-30 20:45:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_wrap() {
|
|
|
|
let num_cols = Column(42);
|
|
|
|
let point = Point::new(1, Column(0));
|
|
|
|
|
|
|
|
let result = point.sub(num_cols, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(0, num_cols - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_clamp() {
|
|
|
|
let num_cols = Column(42);
|
|
|
|
let point = Point::new(0, Column(0));
|
|
|
|
|
|
|
|
let result = point.sub(num_cols, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, point);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add() {
|
|
|
|
let num_cols = Column(42);
|
|
|
|
let point = Point::new(0, Column(13));
|
|
|
|
|
|
|
|
let result = point.add(num_cols, 1);
|
|
|
|
|
2021-01-24 21:45:36 +00:00
|
|
|
assert_eq!(result, Point::new(0, point.column + 1));
|
2020-05-30 20:45:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_wrap() {
|
|
|
|
let num_cols = Column(42);
|
|
|
|
let point = Point::new(0, num_cols - 1);
|
|
|
|
|
|
|
|
let result = point.add(num_cols, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(1, Column(0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_absolute() {
|
|
|
|
let point = Point::new(0, Column(13));
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
let result = point.add_absolute(&(Line(1), Column(42)), Boundary::Clamp, 1);
|
2020-05-30 20:45:44 +00:00
|
|
|
|
2021-01-24 21:45:36 +00:00
|
|
|
assert_eq!(result, Point::new(0, point.column + 1));
|
2020-05-30 20:45:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-07-09 21:45:22 +00:00
|
|
|
fn add_absolute_wrapline() {
|
|
|
|
let point = Point::new(1, Column(41));
|
2020-05-30 20:45:44 +00:00
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
let result = point.add_absolute(&(Line(2), Column(42)), Boundary::Clamp, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(0, Column(0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_absolute_multiline_wrapline() {
|
|
|
|
let point = Point::new(2, Column(9));
|
|
|
|
|
|
|
|
let result = point.add_absolute(&(Line(3), Column(10)), Boundary::Clamp, 11);
|
2020-05-30 20:45:44 +00:00
|
|
|
|
|
|
|
assert_eq!(result, Point::new(0, Column(0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_absolute_clamp() {
|
2020-07-09 21:45:22 +00:00
|
|
|
let point = Point::new(0, Column(41));
|
2020-05-30 20:45:44 +00:00
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
let result = point.add_absolute(&(Line(1), Column(42)), Boundary::Clamp, 1);
|
2020-05-30 20:45:44 +00:00
|
|
|
|
|
|
|
assert_eq!(result, point);
|
|
|
|
}
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
#[test]
|
|
|
|
fn add_absolute_wrap() {
|
|
|
|
let point = Point::new(0, Column(41));
|
|
|
|
|
|
|
|
let result = point.add_absolute(&(Line(3), Column(42)), Boundary::Wrap, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(2, Column(0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_absolute_multiline_wrap() {
|
|
|
|
let point = Point::new(0, Column(9));
|
|
|
|
|
|
|
|
let result = point.add_absolute(&(Line(3), Column(10)), Boundary::Wrap, 11);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(1, Column(0)));
|
|
|
|
}
|
|
|
|
|
2020-05-30 20:45:44 +00:00
|
|
|
#[test]
|
|
|
|
fn sub_absolute() {
|
|
|
|
let point = Point::new(0, Column(13));
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
let result = point.sub_absolute(&(Line(1), Column(42)), Boundary::Clamp, 1);
|
2020-05-30 20:45:44 +00:00
|
|
|
|
2021-01-24 21:45:36 +00:00
|
|
|
assert_eq!(result, Point::new(0, point.column - 1));
|
2020-05-30 20:45:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-07-09 21:45:22 +00:00
|
|
|
fn sub_absolute_wrapline() {
|
2020-05-30 20:45:44 +00:00
|
|
|
let point = Point::new(0, Column(0));
|
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
let result = point.sub_absolute(&(Line(2), Column(42)), Boundary::Clamp, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(1, Column(41)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_absolute_multiline_wrapline() {
|
|
|
|
let point = Point::new(0, Column(0));
|
|
|
|
|
|
|
|
let result = point.sub_absolute(&(Line(3), Column(10)), Boundary::Clamp, 11);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(2, Column(9)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_absolute_wrap() {
|
|
|
|
let point = Point::new(2, Column(0));
|
|
|
|
|
|
|
|
let result = point.sub_absolute(&(Line(3), Column(42)), Boundary::Wrap, 1);
|
|
|
|
|
|
|
|
assert_eq!(result, Point::new(0, Column(41)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_absolute_multiline_wrap() {
|
|
|
|
let point = Point::new(2, Column(0));
|
|
|
|
|
|
|
|
let result = point.sub_absolute(&(Line(3), Column(10)), Boundary::Wrap, 11);
|
2020-05-30 20:45:44 +00:00
|
|
|
|
2020-07-09 21:45:22 +00:00
|
|
|
assert_eq!(result, Point::new(1, Column(9)));
|
2020-05-30 20:45:44 +00:00
|
|
|
}
|
2016-12-22 18:43:06 +00:00
|
|
|
}
|