Create a span type to use instead of the built-in range type

This commit is contained in:
Jesse Braham 2025-01-24 21:20:17 +01:00
parent 8cc6b9d415
commit 4a5b7321e8
2 changed files with 94 additions and 0 deletions

View File

@ -7,4 +7,8 @@
unsafe_code
)]
pub use self::span::Span;
pub mod lexer;
mod span;

90
onihime/src/span.rs Normal file
View File

@ -0,0 +1,90 @@
/// A (half-open) range bounded inclusively below and exclusively above
/// `(start..end)`.
///
/// The range `start..end` contains all values with `start <= x < end`. It is
/// empty if `start >= end`.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Span {
/// The lower bound of the range (inclusive).
pub start: usize,
/// The upper bound of the range (exclusive).
pub end: usize,
}
impl Span {
/// Construct a new instance of a span.
#[must_use]
pub const fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
/// Returns `true` if `item` is contained in the span.
#[must_use]
pub fn contains(&self, item: usize) -> bool {
self.start <= item && item < self.end
}
/// Returns `true` if the span contains no items.
#[must_use]
pub fn is_empty(&self) -> bool {
self.start >= self.end
}
/// Extend the span's end bound to that of the provided span, if
/// `other.end > self.end`.
pub fn extend(&mut self, other: &Self) {
if other.end > self.end {
self.end = other.end;
}
}
}
impl From<std::ops::Range<usize>> for Span {
fn from(range: std::ops::Range<usize>) -> Self {
Self::new(range.start, range.end)
}
}
impl From<Span> for std::ops::Range<usize> {
fn from(span: Span) -> Self {
span.start..span.end
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn span_equality() {
let a = Span::new(0, 0);
let b = Span::new(0, 1);
assert_eq!(a, a);
assert_ne!(a, b);
}
#[test]
fn span_contains() {
let s = Span::new(1, 3);
assert!(s.contains(1));
assert!(s.contains(2));
assert!(!s.contains(0));
assert!(!s.contains(3));
}
#[test]
fn span_extend() {
let mut a = Span::new(0, 5);
let b = Span::new(1, 10);
let c = Span::new(5, 6);
assert_eq!(a.end, 5);
a.extend(&b);
assert_eq!(a.end, 10);
a.extend(&c);
assert_eq!(a.end, 10);
}
}