#[derive(Debug)]
pub struct Input {
input: Vec<char>,
cursor: usize,
}
impl Input {
pub fn new(input: &str) -> Input {
Input {
input: input.trim_end().chars().collect(),
cursor: 0,
}
}
pub fn set_cursor(&mut self, cursor: usize) {
if self.input.len() <= cursor {
self.cursor = self.input.len() - 1;
return;
}
self.cursor = cursor;
}
pub fn get_cursor(&self) -> usize {
self.cursor
}
pub fn next(&mut self) {
if self.cursor < self.input.len() - 1 {
self.cursor += 1;
}
}
pub fn next_char(&mut self) {
if self.cursor < self.input.len() - 1 {
self.cursor += 1;
}
let bgn = self.cursor;
for i in bgn..self.input.len() {
if self.input[i] == ' ' || self.input[i] == '\n' {
if self.cursor == self.input.len() - 1 {
break;
}
self.cursor += 1;
} else {
break;
}
}
}
pub fn is_end(&mut self) -> bool {
if self.cursor == self.input.len() - 1 {
return true;
}
false
}
pub fn expect(&self, exp: char) -> bool {
if self.input[self.cursor] == exp {
return true;
} else {
return false;
}
}
pub fn expect_str(&self, exp: &str) -> bool {
if self.input.len() < self.cursor + exp.len() {
return false;
}
let cursor = self.cursor;
let exp: Vec<char> = exp.chars().collect();
for i in 0..exp.len() {
if exp[i] != self.input[cursor + i] {
return false;
}
}
true
}
pub fn expect_str_insensitive(&self, exp: &str) -> bool {
if self.input.len() < self.cursor + exp.len() {
return false;
}
let cursor = self.cursor;
let exp: Vec<char> = exp.to_lowercase().chars().collect();
for i in 0..exp.len() {
if exp[i] != self.input[cursor + i].to_ascii_lowercase() {
return false;
}
}
true
}
pub fn find(&mut self, needle: char) -> Option<usize> {
let bgn = self.cursor;
if self.input.len() <= bgn {
return None;
}
for i in bgn..self.input.len() {
if self.input[i] == needle {
return Some(i);
}
}
return None;
}
pub fn find_str(&mut self, needle: &str) -> Option<usize> {
let needle: Vec<char> = needle.chars().collect();
let mut i = self.cursor;
if self.input.len() <= i {
return None;
}
let mut bgn_idx;
while i < self.input.len() {
if self.input[i] == needle[0] {
if needle.len() == 1 {
return Some(i);
}
bgn_idx = i;
i += 1;
} else {
i += 1;
continue;
}
let mut j = 1;
while j < needle.len() {
if self.input.len() <= i {
return None;
}
if self.input[i] == needle[j] {
if j == needle.len() - 1 {
return Some(bgn_idx);
}
} else {
break;
}
i += 1;
j += 1;
}
i = bgn_idx + 1;
}
None
}
#[allow(dead_code)]
pub fn get_char(&self, cursor: usize) -> Result<char, String> {
if self.input.len() <= cursor {
return Err(String::from("out of input"));
}
Ok(self.input[cursor])
}
pub fn get_string(&self, bgn: usize, end: usize) -> Result<String, String> {
if end <= bgn {
return Err(String::from("invalid range"));
}
if self.input.len() <= end {
return Err(format!("out of input {:?}:{:?}", bgn, end));
}
let mut s = String::new();
for i in bgn..end {
s.push(self.input[i]);
}
Ok(s)
}
}