use std::cmp;
use std::ops::{Add, Deref, Sub};
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug, Default)]
#[repr(transparent)]
pub struct Pos(pub u32);
impl Add<u64> for Pos {
type Output = Pos;
fn add(self, other: u64) -> Pos {
Pos(self.0 + other as u32)
}
}
impl Sub<Pos> for Pos {
type Output = u64;
fn sub(self, other: Pos) -> u64 {
(self.0 - other.0) as u64
}
}
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
pub(crate) low: Pos,
pub(crate) high: Pos,
}
impl Span {
pub const fn subspan(&self, begin: u64, end: u64) -> Span {
assert!(end >= begin);
assert!(self.low.0 + end as u32 <= self.high.0);
Span {
low: Pos(self.low.0 + begin as u32),
high: Pos(self.low.0 + end as u32),
}
}
pub const fn contains(&self, other: Span) -> bool {
self.low.0 <= other.low.0 && self.high.0 >= other.high.0
}
pub const fn low(&self) -> Pos {
self.low
}
pub const fn high(&self) -> Pos {
self.high
}
pub const fn len(&self) -> u64 {
(self.high.0 - self.low.0) as u64
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn merge(&self, other: Span) -> Span {
Span {
low: cmp::min(self.low, other.low),
high: cmp::max(self.high, other.high),
}
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
pub node: T,
pub span: Span,
}
impl<T> Spanned<T> {
pub fn map_node<U, F: FnOnce(T) -> U>(self, op: F) -> Spanned<U> {
Spanned {
node: op(self.node),
span: self.span,
}
}
}
impl<T> Deref for Spanned<T> {
type Target = T;
fn deref(&self) -> &T {
&self.node
}
}