// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
use miette::SourceSpan;
use std::{
fmt::{self, Display, Formatter},
ops::{Add, Index, Sub},
};
/// A region between two offsets in an array. Spans are the half-open interval `[lo, hi)`.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Span {
/// The smallest offset contained in the span.
pub lo: u32,
/// The next offset after the largest offset contained in the span.
pub hi: u32,
}
impl Span {
/// Returns true if the position is within the span. Meaning it is in the
/// right open interval `[self.lo, self.hi)`.
#[must_use]
pub fn contains(&self, offset: u32) -> bool {
(self.lo..self.hi).contains(&offset)
}
/// Returns true if the position is in the closed interval `[self.lo, self.hi]`.
#[must_use]
pub fn touches(&self, offset: u32) -> bool {
(self.lo..=self.hi).contains(&offset)
}
/// Intersect `other` with `self` and returns a new `Span` or `None`
/// if the spans have no overlap.
#[must_use]
pub fn intersection(&self, other: &Self) -> Option<Self> {
let lo = self.lo.max(other.lo);
let hi = self.hi.min(other.hi);
if lo <= hi {
Some(Self { lo, hi })
} else {
None
}
}
}
impl Add<u32> for Span {
type Output = Self;
fn add(self, rhs: u32) -> Self::Output {
Self {
lo: self.lo + rhs,
hi: self.hi + rhs,
}
}
}
impl Sub<u32> for Span {
type Output = Self;
fn sub(self, rhs: u32) -> Self::Output {
Self {
lo: self.lo - rhs,
hi: self.hi - rhs,
}
}
}
impl Display for Span {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "[{}-{}]", self.lo, self.hi)?;
Ok(())
}
}
impl Index<Span> for str {
type Output = str;
fn index(&self, index: Span) -> &Self::Output {
&self[(index.lo as usize)..(index.hi as usize)]
}
}
impl Index<&Span> for str {
type Output = str;
fn index(&self, index: &Span) -> &Self::Output {
&self[(index.lo as usize)..(index.hi as usize)]
}
}
impl Index<Span> for String {
type Output = str;
fn index(&self, index: Span) -> &Self::Output {
&self[(index.lo as usize)..(index.hi as usize)]
}
}
impl From<Span> for SourceSpan {
fn from(value: Span) -> Self {
Self::from((value.lo as usize)..(value.hi as usize))
}
}
pub trait WithSpan {
#[must_use]
fn with_span(self, span: Span) -> Self;
}
impl<T> WithSpan for Box<T>
where
T: WithSpan,
{
fn with_span(mut self, span: Span) -> Self {
*self = (*self).with_span(span);
self
}
}microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
source/compiler/qsc_data_structures/src/span.rs
120lines · modepreview