pub mod fastparse {
pub mod types {
use std::cmp::{
self as std_cmp,
Ordering,
};
#[derive(Clone, Copy)]
#[derive(Debug)]
#[derive(Eq)]
pub struct PositionalSlice {
pub offset : usize,
pub length : usize,
}
impl PositionalSlice {
pub fn empty() -> Self {
let offset = 0;
let length = 0;
Self {
offset,
length,
}
}
pub fn new(
off : usize,
len : usize,
) -> Self {
Self {
offset : off,
length : len,
}
}
}
impl PositionalSlice {
}
impl PositionalSlice {
pub fn is_empty(&self) -> bool {
0 == self.length
}
pub fn len(&self) -> usize {
self.length
}
pub fn offset_unchecked(
&self,
d : isize,
) -> Self {
let new_off : usize = if d < 0 {
self.offset - (-d) as usize
} else {
self.offset + d as usize
};
Self {
length : self.length,
offset : new_off,
}
}
pub fn offset_checked(
&self,
d : isize,
) -> Option<Self> {
if 0 == d {
return Some(*self);
}
if d < 0 {
let a = (-d) as usize;
if a > self.offset {
return None;
}
Some(Self::new(self.offset - a, self.length))
} else {
debug_assert!(d > 0);
let a = d as usize;
if a > usize::MAX - self.offset {
return None;
}
if a + self.length > usize::MAX - self.offset {
return None;
}
Some(Self::new(self.offset + a, self.length))
}
}
pub fn subslice_of<'a, T>(
&self,
slice : &'a [T],
) -> &'a [T] {
&slice[self.offset..self.offset + self.length]
}
pub fn substring_of<'a>(
&self,
slice : &'a str,
) -> &'a str {
&slice[self.offset..self.offset + self.length]
}
}
impl std_cmp::PartialEq for PositionalSlice {
fn eq(
&self,
other : &Self,
) -> bool {
if self.offset != other.offset {
return false;
}
if self.length != other.length {
return false;
}
true
}
}
impl std_cmp::PartialOrd for PositionalSlice {
fn partial_cmp(
&self,
other : &Self,
) -> Option<Ordering> {
if self.offset < other.offset {
return Some(Ordering::Less);
}
if other.offset < self.offset {
return Some(Ordering::Greater);
}
if self.length < other.length {
return Some(Ordering::Less);
}
if other.length < self.length {
return Some(Ordering::Greater);
}
Some(Ordering::Equal)
}
}
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod tests {
use super::fastparse::types::PositionalSlice;
#[test]
fn PositionalSlice_empty() {
{
let ssi = PositionalSlice::empty();
assert_eq!(0, ssi.offset);
assert_eq!(0, ssi.length);
assert!(ssi.is_empty());
}
}
#[test]
fn PositionalSlice_new() {
{
let ssi = PositionalSlice::new(0, 0);
assert_eq!(0, ssi.offset);
assert_eq!(0, ssi.length);
assert!(ssi.is_empty());
}
{
let ssi = PositionalSlice::new(1, 0);
assert_eq!(1, ssi.offset);
assert_eq!(0, ssi.length);
assert!(ssi.is_empty());
}
{
let ssi = PositionalSlice::new(0, 1);
assert_eq!(0, ssi.offset);
assert_eq!(1, ssi.length);
assert!(!ssi.is_empty());
}
}
#[test]
fn PositionalSlice_clone() {
let ssi1 = PositionalSlice::new(10, 13);
let ssi2 = ssi1.clone();
assert_eq!(ssi1, ssi2);
}
#[test]
fn PositionalSlice_copy() {
let ssi1 = PositionalSlice::new(10, 13);
let ssi2 = ssi1;
assert_eq!(ssi1, ssi2);
}
#[test]
fn PositionalSlice_op_eq() {
assert_eq!(PositionalSlice::new(0, 0), PositionalSlice::new(0, 0));
assert_ne!(PositionalSlice::new(0, 0), PositionalSlice::new(1, 0));
assert_ne!(PositionalSlice::new(0, 0), PositionalSlice::new(0, 1));
assert_ne!(PositionalSlice::new(0, 0), PositionalSlice::new(1, 1));
}
#[test]
fn PositionalSlice_op_lt() {
assert!(!(PositionalSlice::new(0, 0) < PositionalSlice::new(0, 0)));
assert!(!(PositionalSlice::new(0, 0) > PositionalSlice::new(0, 0)));
assert!(PositionalSlice::new(0, 1) < PositionalSlice::new(1, 1));
assert!(PositionalSlice::new(1, 1) > PositionalSlice::new(0, 1));
assert!(PositionalSlice::new(0, 1) < PositionalSlice::new(0, 2));
assert!(PositionalSlice::new(0, 2) > PositionalSlice::new(0, 1));
}
#[test]
fn PositionalSlice_offset_unchecked() {
{
let ssi1 = PositionalSlice::new(0, 1);
let ssi2 = ssi1.offset_unchecked(1);
assert_eq!(PositionalSlice::new(1, 1), ssi2);
}
{
let ssi1 = PositionalSlice::new(1, 1);
let ssi2 = ssi1.offset_unchecked(-1);
assert_eq!(PositionalSlice::new(0, 1), ssi2);
}
#[cfg(not(debug_assertions))]
{
let ssi1 = PositionalSlice::new(0, 1);
let ssi2 = ssi1.offset_unchecked(-1);
assert_eq!(PositionalSlice::new(std::usize::MAX, 1), ssi2);
}
}
#[cfg(debug_assertions)]
#[test]
#[should_panic(expected = "attempt to subtract with overflow")]
fn PositionalSlice_offset_unchecked_() {
{
let ssi1 = PositionalSlice::new(0, 1);
let _ssi2 = ssi1.offset_unchecked(-1);
panic!("should not get here");
}
}
#[test]
fn PositionalSlice_offset_checked() {
{
let ssi1 = PositionalSlice::new(0, 1);
let ssi2 = ssi1.offset_checked(1);
assert!(ssi2.is_some());
assert_eq!(PositionalSlice::new(1, 1), ssi2.unwrap());
}
{
let ssi1 = PositionalSlice::new(1, 1);
let ssi2 = ssi1.offset_checked(-1);
assert!(ssi2.is_some());
assert_eq!(PositionalSlice::new(0, 1), ssi2.unwrap());
}
{
let ssi1 = PositionalSlice::new(0, 1);
let ssi2 = ssi1.offset_checked(-1);
assert!(ssi2.is_none());
}
{
let ssi1 = PositionalSlice::new(usize::MAX - 2, 1);
let ssi2 = ssi1.offset_checked(1);
assert!(ssi2.is_some());
assert_eq!(PositionalSlice::new(usize::MAX - 1, 1), ssi2.unwrap());
}
{
let ssi1 = PositionalSlice::new(usize::MAX - 2, 1);
let ssi2 = ssi1.offset_checked(2);
assert!(ssi2.is_none());
}
}
#[test]
fn PositionalSlice_subslice_of() {
{
let ps = PositionalSlice::new(2, 2);
let source = vec![
0, 1, 2, 3, 4, 5, 6,
];
let sub = ps.subslice_of(&source);
assert_eq!(2, sub.len());
assert_eq!(2, sub[0]);
assert_eq!(3, sub[1]);
}
{
let ps = PositionalSlice::new(2, 2);
let source = vec![
0, 1, 2, 3, 4, 5, 6,
];
let sub = ps.subslice_of(&source[1..]);
assert_eq!(2, sub.len());
assert_eq!(3, sub[0]);
assert_eq!(4, sub[1]);
}
}
#[test]
fn PositionalSlice_substring_of() {
{
let ps = PositionalSlice::new(2, 2);
let source = "abcdef".to_string();
let sub = ps.substring_of(&source[..]);
assert_eq!("cd", sub);
}
{
let ps = PositionalSlice::new(2, 2);
let source = "abcdef".to_string();
let sub = ps.substring_of(&source[1..]);
assert_eq!("de", sub);
}
}
}