use core::cmp;
use core::fmt;
use core::ops;
use serde::{Deserialize, Serialize};
use crate::ast::prelude::*;
#[derive(Default, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[try_clone(copy)]
pub struct Span {
pub start: ByteIndex,
pub end: ByteIndex,
}
impl Span {
pub fn new<S, E>(start: S, end: E) -> Self
where
S: TryInto<ByteIndex>,
S::Error: fmt::Debug,
E: TryInto<ByteIndex>,
E::Error: fmt::Debug,
{
Self {
start: start.try_into().expect("start out of bounds"),
end: end.try_into().expect("end out of bounds"),
}
}
pub fn point<P>(pos: P) -> Self
where
P: TryInto<ByteIndex>,
P::Error: fmt::Debug,
{
let pos = pos.try_into().expect("point out of bounds");
Self {
start: pos,
end: pos,
}
}
pub const fn empty() -> Self {
Self {
start: ByteIndex(0),
end: ByteIndex(0),
}
}
pub fn head(self) -> Self {
Self {
start: self.start,
end: self.start,
}
}
pub fn tail(self) -> Self {
Self {
start: self.end,
end: self.end,
}
}
pub fn join(self, other: Self) -> Self {
Self {
start: ByteIndex::min(self.start, other.start),
end: ByteIndex::max(self.end, other.end),
}
}
pub fn narrow(self, amount: impl Into<ByteIndex>) -> Self {
let amount = amount.into();
let end = ByteIndex::max(self.start, self.end.saturating_sub(amount));
let start = ByteIndex::min(self.start.saturating_add(amount), end);
Self { start, end }
}
pub fn range(self) -> ops::Range<usize> {
ops::Range {
start: usize::try_from(self.start.0).expect("start index out of bounds"),
end: usize::try_from(self.end.0).expect("end index out of bounds"),
}
}
pub(crate) fn trim_start(self, amount: impl Into<ByteIndex>) -> Self {
let amount = amount.into();
Self {
start: ByteIndex::min(self.start.saturating_add(amount), self.end),
end: self.end,
}
}
pub(crate) fn trim_end(self, amount: impl Into<ByteIndex>) -> Self {
let amount = amount.into();
Self {
start: self.start,
end: ByteIndex::max(self.end.saturating_sub(amount), self.start),
}
}
}
impl Serialize for Span {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
(self.start, self.end).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Span {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let (start, end) = <(ByteIndex, ByteIndex)>::deserialize(deserializer)?;
Ok(Self { start, end })
}
}
impl fmt::Display for Span {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "{}:{}", self.start, self.end)
}
}
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.start, self.end)
}
}
#[derive(
Default, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
#[repr(transparent)]
#[serde(transparent)]
#[try_clone(copy)]
pub struct ByteIndex(#[doc(hidden)] pub u32);
impl ByteIndex {
pub fn into_usize(self) -> usize {
usize::try_from(self.0).expect("byte index out of range")
}
fn min(a: Self, b: Self) -> Self {
Self(u32::min(a.0, b.0))
}
fn max(a: Self, b: Self) -> Self {
Self(u32::max(a.0, b.0))
}
pub(crate) fn saturating_sub(self, other: Self) -> Self {
Self(self.0.saturating_sub(other.0))
}
fn saturating_add(self, other: Self) -> Self {
Self(self.0.saturating_add(other.0))
}
}
impl From<u32> for ByteIndex {
fn from(value: u32) -> Self {
Self(value)
}
}
impl TryFrom<usize> for ByteIndex {
type Error = <usize as TryFrom<u32>>::Error;
fn try_from(value: usize) -> Result<Self, Self::Error> {
Ok(Self(u32::try_from(value)?))
}
}
impl TryFrom<i32> for ByteIndex {
type Error = <i32 as TryFrom<u32>>::Error;
fn try_from(value: i32) -> Result<Self, Self::Error> {
Ok(Self(u32::try_from(value)?))
}
}
impl fmt::Display for ByteIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for ByteIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl cmp::PartialEq<usize> for ByteIndex {
fn eq(&self, other: &usize) -> bool {
match u32::try_from(*other) {
Ok(other) => self.0 == other,
Err(..) => false,
}
}
}
impl cmp::PartialEq<u32> for ByteIndex {
fn eq(&self, other: &u32) -> bool {
self.0 == *other
}
}