feat(Source): impl Source for str, &str (make &'static str usable for testing) (#40)

This commit is contained in:
Cormac Relf 2021-08-30 12:07:07 +10:00 committed by GitHub
parent 5d5e33d108
commit 50c7a88360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 63 additions and 33 deletions

View File

@ -5,12 +5,11 @@ use std::{borrow::Cow, sync::Arc};
use crate::{MietteError, MietteSpanContents, Source, SourceSpan, SpanContents}; use crate::{MietteError, MietteSpanContents, Source, SourceSpan, SpanContents};
impl Source for String { fn start_line_column(string: &str, span: &SourceSpan) -> Result<(usize, usize), MietteError> {
fn read_span(&self, span: &SourceSpan) -> Result<Box<dyn SpanContents + '_>, MietteError> {
let mut offset = 0usize; let mut offset = 0usize;
let mut start_line = 0usize; let mut start_line = 0usize;
let mut start_column = 0usize; let mut start_column = 0usize;
let mut iter = self.chars().peekable(); let mut iter = string.chars().peekable();
while let Some(char) = iter.next() { while let Some(char) = iter.next() {
if offset < span.offset() { if offset < span.offset() {
match char { match char {
@ -32,16 +31,47 @@ impl Source for String {
} }
if offset >= span.offset() + span.len() - 1 { 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( return Ok(Box::new(MietteSpanContents::new(
&self.as_bytes()[span.offset()..span.offset() + span.len()], &self.as_bytes()[span.offset()..span.offset() + span.len()],
start_line, start_line,
start_column, start_column,
))); )));
} }
offset += char.len_utf8();
} }
Err(MietteError::OutOfBounds)
/// 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)
} }
} }