#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Span {
pub start: usize,
pub end: usize,
}
pub type Spanned<T> = (T, Span);
impl Span {
pub fn new(start: usize, end: usize) -> Self {
debug_assert!(
start <= end,
"[Span::new] `start: {start}` is located after `end: {end}`"
);
Self { start, end }
}
pub fn new_between(a: Span, b: Span) -> Self {
debug_assert!(
a.end <= b.start,
"[Span::new_between] `a.end: {}` is located after `b.start: {}`",
a.end,
b.start
);
Self {
start: a.end,
end: b.start,
}
}
pub fn new_zero_width(position: usize) -> Self {
Self {
start: position,
end: position,
}
}
pub fn is_zero_width(&self) -> bool {
self.start == self.end
}
pub fn is_before(&self, span: &Self) -> bool {
self.end <= span.start
}
pub fn is_after(&self, span: &Self) -> bool {
self.start >= span.end
}
pub fn is_before_pos(&self, pos: usize) -> bool {
self.end <= pos
}
pub fn is_after_pos(&self, pos: usize) -> bool {
self.start >= pos
}
pub fn starts_at_or_after(&self, position: usize) -> bool {
self.start >= position
}
pub fn contains(&self, span: Self) -> bool {
self.start <= span.start && span.end <= self.end
}
pub fn contains_pos(&self, position: usize) -> bool {
self.start <= position && position <= self.end
}
pub fn end_at_previous(self) -> Self {
let new_end = self.end.saturating_sub(1);
Self {
start: usize::min(self.start, new_end),
end: new_end,
}
}
pub fn first_char(self) -> Self {
Self {
start: self.start,
end: usize::min(self.start.saturating_add(1), self.end),
}
}
pub fn last_char(self) -> Self {
Self {
start: usize::max(self.end.saturating_sub(1), self.start),
end: self.end,
}
}
pub fn start_zero_width(self) -> Self {
Self {
start: self.start,
end: self.start,
}
}
pub fn end_zero_width(self) -> Self {
Self {
start: self.end,
end: self.end,
}
}
pub fn next_single_width(self) -> Self {
Self {
start: self.end,
end: self.end.saturating_add(1),
}
}
pub fn previous_single_width(self) -> Self {
Self {
start: self.start.saturating_sub(1),
end: self.start,
}
}
}
impl std::fmt::Debug for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}-{}", self.start, self.end)
}
}
impl std::fmt::Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SpanEncoding {
Utf8,
Utf16,
Utf32,
}
#[cfg(test)]
pub(crate) fn span(start: usize, end: usize) -> Span {
Span { start, end }
}