use core::fmt;
use core::mem::size_of;
use core::ops;
use core::ops::Range;
use crate::builder::Id;
use crate::non_max::NonMax;
#[cfg(syntree_compact)]
pub(crate) type Index = u32;
#[cfg(syntree_compact)]
#[inline]
pub(crate) fn usize_to_index(value: usize) -> Option<u32> {
u32::try_from(value).ok()
}
#[cfg(not(syntree_compact))]
pub(crate) type Index = usize;
#[cfg(not(syntree_compact))]
#[inline]
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn usize_to_index(value: usize) -> Option<Index> {
Some(value)
}
const _: () = assert!(size_of::<Index>() <= size_of::<usize>());
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct Span {
pub start: Index,
pub end: Index,
}
impl Span {
#[must_use]
pub const fn new(start: Index, end: Index) -> Self {
assert!(start <= end, "start of the span must come before end");
Self { start, end }
}
#[must_use]
pub const fn point(at: Index) -> Self {
Self { start: at, end: at }
}
#[must_use]
pub const fn join(&self, other: &Self) -> Self {
Self {
start: if self.start < other.start {
self.start
} else {
other.start
},
end: if self.end > other.end {
self.end
} else {
other.end
},
}
}
#[allow(clippy::unnecessary_cast)]
#[must_use]
pub const fn range(self) -> ops::Range<usize> {
(self.start as usize)..(self.end as usize)
}
#[must_use]
pub const fn len(&self) -> Index {
self.end.saturating_sub(self.start)
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.end == self.start
}
#[must_use]
pub const fn contains(self, index: Index) -> bool {
self.start <= index && index < self.end
}
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(&self.start, &self.end).fmt(f)
}
}
impl PartialEq<&Span> for Span {
#[inline]
fn eq(&self, other: &&Span) -> bool {
*self == **other
}
}
impl PartialEq<Span> for &Span {
#[inline]
fn eq(&self, other: &Span) -> bool {
**self == *other
}
}
mod sealed {
pub trait Sealed {}
impl Sealed for super::Span {}
impl Sealed for super::Empty {}
impl Sealed for usize {}
impl Sealed for Vec<super::TreeIndex> {}
}
pub trait TreeSpan: self::sealed::Sealed + Copy {
#[doc(hidden)]
const EMPTY: Self;
#[doc(hidden)]
const INDEXES: Self::Indexes;
#[doc(hidden)]
type Length: Length;
#[doc(hidden)]
type Indexes: Indexes;
#[doc(hidden)]
fn point(index: Index) -> Self;
#[doc(hidden)]
fn new(start: Index, end: Index) -> Self;
#[doc(hidden)]
fn start(&self) -> Index;
#[doc(hidden)]
fn end(&self) -> Index;
#[doc(hidden)]
fn set_end(&mut self, end: Index);
#[doc(hidden)]
fn len(&self) -> Index;
#[doc(hidden)]
fn range(self) -> Range<usize>;
}
#[doc(hidden)]
pub trait Length: self::sealed::Sealed + Copy {
#[doc(hidden)]
const EMPTY: Self;
#[doc(hidden)]
fn is_empty(&self) -> bool;
#[doc(hidden)]
fn into_index(self) -> Option<Index>;
}
#[doc(hidden)]
pub trait Indexes: self::sealed::Sealed {
#[doc(hidden)]
fn push(&mut self, cursor: Index, id: Id);
#[doc(hidden)]
fn binary_search(&self, index: Index) -> Result<usize, usize>;
#[doc(hidden)]
fn get(&self, index: usize) -> Option<Id>;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct TreeIndex {
pub(crate) index: Index,
pub(crate) id: NonMax,
}
impl From<Empty> for usize {
#[inline]
fn from(Empty: Empty) -> Self {
0
}
}
impl Indexes for Vec<TreeIndex> {
#[inline]
fn push(&mut self, index: Index, Id(id): Id) {
Vec::push(self, TreeIndex { index, id })
}
#[inline]
fn binary_search(&self, index: Index) -> Result<usize, usize> {
self.binary_search_by(|f| f.index.cmp(&index))
}
#[inline]
fn get(&self, index: usize) -> Option<Id> {
Some(Id(<[_]>::get(self, index)?.id))
}
}
impl Length for usize {
const EMPTY: Self = 0;
#[inline]
fn is_empty(&self) -> bool {
*self == 0
}
#[inline]
fn into_index(self) -> Option<Index> {
usize_to_index(self)
}
}
impl TreeSpan for Span {
const EMPTY: Self = Span::point(0);
const INDEXES: Self::Indexes = Vec::new();
type Length = usize;
type Indexes = Vec<TreeIndex>;
#[inline]
fn point(index: Index) -> Self {
Span::point(index)
}
#[inline]
fn new(start: Index, end: Index) -> Self {
Span::new(start, end)
}
#[inline]
fn start(&self) -> Index {
self.start
}
#[inline]
fn end(&self) -> Index {
self.end
}
#[inline]
fn set_end(&mut self, end: Index) {
self.end = end;
}
#[inline]
fn len(&self) -> Index {
Span::len(self)
}
#[inline]
fn range(self) -> Range<usize> {
Span::range(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Empty;
impl TreeSpan for Empty {
const EMPTY: Self = Empty;
const INDEXES: Self::Indexes = Empty;
type Length = Empty;
type Indexes = Empty;
#[inline]
fn point(_: Index) -> Self {
Empty
}
#[inline]
fn new(_: Index, _: Index) -> Self {
Empty
}
#[inline]
fn start(&self) -> Index {
0
}
#[inline]
fn end(&self) -> Index {
0
}
#[inline]
fn set_end(&mut self, _: Index) {}
#[inline]
fn len(&self) -> Index {
0
}
#[inline]
fn range(self) -> Range<usize> {
0..0
}
}
impl Length for Empty {
const EMPTY: Self = Empty;
#[inline]
fn is_empty(&self) -> bool {
true
}
#[inline]
fn into_index(self) -> Option<Index> {
Some(0)
}
}
impl Indexes for Empty {
#[inline]
fn push(&mut self, _: Index, _: Id) {}
#[inline]
fn binary_search(&self, _: Index) -> Result<usize, usize> {
Err(0)
}
#[inline]
fn get(&self, _: usize) -> Option<Id> {
None
}
}