use core::fmt;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct Span {
pub start: u32,
pub end: u32,
}
impl Span {
#[inline]
#[must_use]
pub const fn new(start: u32, end: u32) -> Self {
Self { start, end }
}
#[inline]
#[must_use]
pub const fn point(offset: u32) -> Self {
Self {
start: offset,
end: offset,
}
}
#[inline]
#[must_use]
pub const fn len(self) -> u32 {
self.end - self.start
}
#[inline]
#[must_use]
pub const fn is_empty(self) -> bool {
self.start == self.end
}
#[inline]
#[must_use]
pub fn to(self, other: Span) -> Span {
Span {
start: self.start.min(other.start),
end: self.end.max(other.end),
}
}
#[inline]
#[must_use]
pub fn slice(self, source: &str) -> &str {
&source[self.start as usize..self.end as usize]
}
}
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
#[cfg(test)]
mod tests {
use super::Span;
#[test]
fn len_and_empty() {
assert_eq!(Span::new(3, 8).len(), 5);
assert!(Span::point(4).is_empty());
assert!(!Span::new(3, 8).is_empty());
}
#[test]
fn merge() {
assert_eq!(Span::new(2, 5).to(Span::new(7, 9)), Span::new(2, 9));
assert_eq!(Span::new(7, 9).to(Span::new(2, 5)), Span::new(2, 9));
}
#[test]
fn slice() {
let src = "let x = 42;";
assert_eq!(Span::new(4, 5).slice(src), "x");
assert_eq!(Span::new(8, 10).slice(src), "42");
}
}