ray-tracing2/ray-tracing-pbrt-scene/src/error.rs
2025-08-08 12:57:46 +02:00

116 lines
2.7 KiB
Rust

use std::{io::Read, path::PathBuf};
use miette::{SourceCode, SourceSpan, SpanContents};
#[derive(Debug)]
pub struct SourceFile {
pub(crate) path: PathBuf,
}
impl SourceCode for SourceFile {
fn read_span<'a>(
&'a self,
span: &miette::SourceSpan,
context_lines_before: usize,
context_lines_after: usize,
) -> std::result::Result<Box<dyn miette::SpanContents<'a> + 'a>, miette::MietteError> {
let mut file = std::fs::File::open(&self.path)?;
// read keeping the last
let mut data = Vec::new();
file.read_to_end(&mut data)?;
let data = data.leak();
let line = data.iter().filter(|&&x| x == b'\n').count();
let mut start_new_lines = 0;
let start_pos = data[0..span.offset()]
.iter()
.rposition(|&x| {
if x == b'\n' {
if start_new_lines > context_lines_before {
true
} else {
start_new_lines += 1;
false
}
} else {
false
}
})
.map(|x| x + 1)
.unwrap_or(0);
let mut end_new_lines = 0;
let end_pos = data[span.offset()..]
.iter()
.position(|&x| {
if x == b'\n' {
if end_new_lines >= context_lines_after {
true
} else {
end_new_lines += 1;
false
}
} else {
false
}
})
.map(|x| x + span.offset())
.unwrap_or(data.len());
let compact_data = &data[start_pos..end_pos];
Ok(Box::new(SourceFileSpanContents {
span: SourceSpan::new(start_pos.into(), end_pos - start_pos),
start_line_number: line - start_new_lines,
line_count: start_new_lines + 1 + end_new_lines,
path: self.path.clone(),
data: compact_data,
}))
}
}
#[derive(Debug)]
struct SourceFileSpanContents {
data: &'static [u8],
span: SourceSpan,
start_line_number: usize,
line_count: usize,
path: PathBuf,
}
impl<'a> SpanContents<'a> for SourceFileSpanContents {
fn data(&'_ self) -> &'a [u8] {
self.data
}
fn span(&self) -> &SourceSpan {
&self.span
}
fn line(&self) -> usize {
self.start_line_number
}
fn column(&self) -> usize {
0
}
fn line_count(&self) -> usize {
self.line_count
}
fn name(&self) -> Option<&str> {
self.path.to_str()
}
fn language(&self) -> Option<&str> {
None
}
}