Implement slice, take, and compare.

This commit is contained in:
Tom Alexander 2023-08-22 17:50:41 -04:00
parent 1e3dadd458
commit e4656cddf6
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
1 changed files with 80 additions and 3 deletions

View File

@ -1,4 +1,6 @@
use nom::bytes::complete::tag; use std::ops::RangeBounds;
use nom::{bytes::complete::tag, Compare, InputTake, Slice};
fn main() { fn main() {
let input = "this is my test input".to_owned(); let input = "this is my test input".to_owned();
@ -11,11 +13,86 @@ fn main() {
#[derive(Debug)] #[derive(Debug)]
struct WrappedInput<'s> { struct WrappedInput<'s> {
contents: &'s str, full_source: &'s str,
start: usize,
end: usize, //exclusive
preceding_line_break: Option<usize>,
} }
impl<'s> WrappedInput<'s> { impl<'s> WrappedInput<'s> {
/// Returns a wrapped string that keeps track of values we need for parsing org-mode.
///
/// Only call this on the full original string. Calling this on a substring can result in invalid values.
pub fn new(input: &'s str) -> Self { pub fn new(input: &'s str) -> Self {
WrappedInput { contents: input } WrappedInput {
full_source: input,
start: 0,
end: input.len(),
preceding_line_break: None,
}
}
}
impl<'s> InputTake for WrappedInput<'s> {
fn take(&self, count: usize) -> Self {
self.slice(..count)
}
fn take_split(&self, count: usize) -> (Self, Self) {
(self.slice(count..), self.slice(..count))
}
}
impl<'s, O: Into<&'s str>> Compare<O> for WrappedInput<'s> {
fn compare(&self, t: O) -> nom::CompareResult {
(&self.full_source[self.start..self.end]).compare(t.into())
}
fn compare_no_case(&self, t: O) -> nom::CompareResult {
(&self.full_source[self.start..self.end]).compare_no_case(t.into())
}
}
impl<'s> From<&'s str> for WrappedInput<'s> {
fn from(value: &'s str) -> Self {
WrappedInput::new(value)
}
}
impl<'s> From<&WrappedInput<'s>> for &'s str {
fn from(value: &WrappedInput<'s>) -> Self {
&value.full_source[value.start..value.end]
}
}
impl<'s, R> Slice<R> for WrappedInput<'s>
where
R: RangeBounds<usize>,
{
fn slice(&self, range: R) -> Self {
let new_start = match range.start_bound() {
std::ops::Bound::Included(idx) => self.start + idx,
std::ops::Bound::Excluded(idx) => self.start + idx - 1,
std::ops::Bound::Unbounded => self.start,
};
let new_end = match range.end_bound() {
std::ops::Bound::Included(idx) => self.start + idx,
std::ops::Bound::Excluded(idx) => self.start + idx - 1,
std::ops::Bound::Unbounded => self.start,
};
// TODO: calculate updated values for WrappedInput
WrappedInput {
full_source: self.full_source,
start: new_start,
end: new_end,
preceding_line_break: None,
}
}
}
impl<'s> std::fmt::Display for WrappedInput<'s> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
Into::<&str>::into(self).fmt(f)
} }
} }