huff_neo_utils/file/
span.rs1use crate::file::file_source::FileSource;
2use serde::{Deserialize, Serialize};
3use std::ops::{Add, Range};
4use std::sync::Arc;
5
6#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
8pub struct Span {
9 pub start: usize,
11 pub end: usize,
13 pub file: Option<Arc<FileSource>>,
15}
16
17impl Span {
18 pub const EOF: Span = Span { start: 0, end: 0, file: None };
20
21 pub fn new(Range { start, end }: Range<usize>, file: Option<Arc<FileSource>>) -> Self {
23 Self { start, end, file }
24 }
25
26 pub fn range(&self) -> Option<Range<usize>> {
28 (*self != Self::EOF).then_some(self.start..self.end)
29 }
30
31 pub fn identifier(&self) -> String {
33 self.file.as_ref().map(|f| format!("\n-> {}", f.path)).unwrap_or_default()
34 }
35
36 pub fn source_seg(&self) -> String {
38 self.file
39 .as_ref()
40 .map(|f| {
41 f.source
42 .as_ref()
43 .map(|s| {
44 if self.start >= s.len() {
45 return format!(
47 "\nInternal compiler error: Start index out of range file={}, start={}, end={}, len={}.",
48 self.file.clone().unwrap_or_default().path,
49 self.start,
50 self.end,
51 s.len()
52 );
53 }
54 let line_num = &s.as_bytes()[0..self.start].iter().filter(|&&c| c == b'\n').count() + 1;
55 let line_start = &s[0..self.start].rfind('\n').unwrap_or(0);
56 let line_end = self.end + s[self.end..s.len()].find('\n').unwrap_or(s.len() - self.end).to_owned();
57 let padding = (0..line_num.to_string().len()).map(|_| " ").collect::<String>();
58 format!(
59 "\n {}|\n > {} | {}\n {}|",
60 padding,
61 line_num,
62 s[line_start.to_owned()..line_end].replace('\n', ""),
63 padding
64 )
65 })
66 .unwrap_or_default()
67 })
68 .unwrap_or_default()
69 }
70}
71
72impl From<Span> for Range<usize> {
73 fn from(span: Span) -> Self {
74 span.range().unwrap()
75 }
76}
77
78impl From<Range<usize>> for Span {
79 fn from(Range { start, end }: Range<usize>) -> Self {
80 Self { start, end, file: None }
81 }
82}
83
84impl Add for Span {
85 type Output = Span;
86
87 fn add(self, rhs: Span) -> Self::Output {
88 Span::new(self.start..rhs.end, None)
89 }
90}
91
92pub trait Spanned {
94 fn span(&self) -> Span;
96}
97
98pub struct WithSpan<T> {
100 pub value: T,
102 pub span: Span,
104}
105
106impl<T> WithSpan<T> {
107 pub fn new(value: T, span: Span) -> Self {
109 Self { value, span }
110 }
111}
112
113impl<T> Spanned for WithSpan<T> {
114 fn span(&self) -> Span {
115 self.span.clone()
116 }
117}