mirror of https://github.com/zkat/miette.git
feat(Source): impl Source for str, &str (make &'static str usable for testing) (#40)
This commit is contained in:
parent
5d5e33d108
commit
50c7a88360
|
|
@ -5,43 +5,73 @@ use std::{borrow::Cow, sync::Arc};
|
|||
|
||||
use crate::{MietteError, MietteSpanContents, Source, SourceSpan, SpanContents};
|
||||
|
||||
impl Source for String {
|
||||
fn read_span(&self, span: &SourceSpan) -> Result<Box<dyn SpanContents + '_>, MietteError> {
|
||||
let mut offset = 0usize;
|
||||
let mut start_line = 0usize;
|
||||
let mut start_column = 0usize;
|
||||
let mut iter = self.chars().peekable();
|
||||
while let Some(char) = iter.next() {
|
||||
if offset < span.offset() {
|
||||
match char {
|
||||
'\r' => {
|
||||
if iter.next_if_eq(&'\n').is_some() {
|
||||
offset += 1;
|
||||
}
|
||||
start_line += 1;
|
||||
start_column = 0;
|
||||
}
|
||||
'\n' => {
|
||||
start_line += 1;
|
||||
start_column = 0;
|
||||
}
|
||||
_ => {
|
||||
start_column += 1;
|
||||
fn start_line_column(string: &str, span: &SourceSpan) -> Result<(usize, usize), MietteError> {
|
||||
let mut offset = 0usize;
|
||||
let mut start_line = 0usize;
|
||||
let mut start_column = 0usize;
|
||||
let mut iter = string.chars().peekable();
|
||||
while let Some(char) = iter.next() {
|
||||
if offset < span.offset() {
|
||||
match char {
|
||||
'\r' => {
|
||||
if iter.next_if_eq(&'\n').is_some() {
|
||||
offset += 1;
|
||||
}
|
||||
start_line += 1;
|
||||
start_column = 0;
|
||||
}
|
||||
'\n' => {
|
||||
start_line += 1;
|
||||
start_column = 0;
|
||||
}
|
||||
_ => {
|
||||
start_column += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if offset >= span.offset() + span.len() - 1 {
|
||||
return Ok(Box::new(MietteSpanContents::new(
|
||||
&self.as_bytes()[span.offset()..span.offset() + span.len()],
|
||||
start_line,
|
||||
start_column,
|
||||
)));
|
||||
}
|
||||
|
||||
offset += char.len_utf8();
|
||||
}
|
||||
Err(MietteError::OutOfBounds)
|
||||
|
||||
if offset >= span.offset() + span.len() - 1 {
|
||||
return Ok((start_line, start_column));
|
||||
}
|
||||
|
||||
offset += char.len_utf8();
|
||||
}
|
||||
Err(MietteError::OutOfBounds)
|
||||
}
|
||||
|
||||
// The basic impl here is on str (not &str), because otherwise String's impl cannot reuse it
|
||||
// without creating a temporary &str inside its read_span implementation, and then returning data
|
||||
// that refers to that temporary.
|
||||
impl Source for str {
|
||||
fn read_span<'a>(
|
||||
&'a self,
|
||||
span: &SourceSpan,
|
||||
) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
|
||||
let (start_line, start_column) = start_line_column(self, span)?;
|
||||
return Ok(Box::new(MietteSpanContents::new(
|
||||
&self.as_bytes()[span.offset()..span.offset() + span.len()],
|
||||
start_line,
|
||||
start_column,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes `src: &'static str` or `struct S<'a> { src: &'a str }` usable.
|
||||
impl<'s> Source for &'s str {
|
||||
fn read_span<'a>(
|
||||
&'a self,
|
||||
span: &SourceSpan,
|
||||
) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
|
||||
<str as Source>::read_span(self, span)
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for String {
|
||||
fn read_span<'a>(
|
||||
&'a self,
|
||||
span: &SourceSpan,
|
||||
) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
|
||||
<str as Source>::read_span(self, span)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue