use std::ops::{Deref, Index, RangeFrom};
#[derive(Debug, Clone)]
pub struct Input<T> {
input: T,
length: usize,
position: usize,
}
impl<'i> From<&'i str> for Input<&'i str> {
fn from(value: &'i str) -> Self {
Input {
input: value,
length: value.len(),
position: 0,
}
}
}
impl<'i, T> From<&'i [T]> for Input<&'i [T]> {
fn from(value: &'i [T]) -> Self {
Input {
input: value,
length: value.len(),
position: 0,
}
}
}
impl PartialEq<&str> for Input<&str> {
fn eq(&self, other: &&str) -> bool {
&self.input[self.position..] == *other
}
}
impl<T> PartialEq<&[T]> for Input<&[T]>
where
[T]: Eq,
{
fn eq(&self, other: &&[T]) -> bool {
&self.input[self.position..] == *other
}
}
impl<T> Deref for Input<T>
where
T: Deref,
<T as Deref>::Target: Index<RangeFrom<usize>>,
{
type Target = <<T as Deref>::Target as Index<RangeFrom<usize>>>::Output;
fn deref(&self) -> &Self::Target {
&self.input[self.position..]
}
}
impl<T> Input<T>
where
T: Clone,
{
pub fn pop(&self, count: usize) -> Input<T> {
let offset = if self.position + count <= self.length {
count
} else {
0
};
Input {
input: self.input.clone(),
length: self.length,
position: self.position + offset,
}
}
}
impl<T> Input<T> {
pub fn get_position(&self) -> usize {
self.position
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_equality() {
let str = "A";
let input = Input::from(str);
assert_eq!(input, str);
assert_eq!(input, "A");
let slice = &[0, 2, 4][..];
let input = Input::from(slice);
assert_eq!(input, slice);
assert_eq!(input, &[0, 2, 4]);
}
#[test]
fn test_deref_magic() {
let str = "ABC";
let input = Input::from(str);
assert_eq!(input, "ABC");
let input = input.pop(1);
assert_eq!(input, "BC");
assert_eq!(&input[0..], "BC");
let input = input.pop(1);
assert_eq!(input, "C");
assert_eq!(&input[0..], "C");
let input = input.pop(1);
assert_eq!(input, "");
assert_eq!(&input[0..], "");
let input = input.pop(10).pop(1).pop(3);
assert_eq!(input, "");
assert_eq!(&input[0..], "");
}
}