use crate::_impl_init;
#[doc = crate::_tags!(text)]
#[doc = crate::_doc_location!("text")]
pub type TextUnit = u32;
#[must_use]
#[doc = crate::_tags!(text layout)]
#[doc = crate::_doc_location!("text")]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TextIndex(pub u32);
_impl_init![ConstInit: Self(0) => TextIndex];
#[rustfmt::skip]
impl TextIndex {
pub const fn new(value: u32) -> Self { Self(value) }
pub const fn next(self) -> Self { Self(self.0 + 1) }
pub const fn checked_next(self) -> Option<Self> {
match self.0.checked_add(1) {
Some(v) => Some(Self(v)),
None => None,
}
}
pub const fn as_usize(self) -> usize { self.0 as usize }
}
#[must_use]
#[doc = crate::_tags!(text)]
#[doc = crate::_doc_location!("text")]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct TextCursor {
pub index: TextIndex,
}
_impl_init![ConstInit: Self::new_prim(0) => TextCursor];
impl TextCursor {
pub const fn new(index: TextIndex) -> Self {
Self { index }
}
pub const fn new_prim(index: TextUnit) -> Self {
Self { index: TextIndex(index) }
}
}
#[must_use]
#[doc = crate::_tags!(text)]
#[doc = crate::_doc_location!("text")]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TextRange {
pub start: TextIndex,
pub end: TextIndex,
}
_impl_init![ConstInit: Self::from_prim(0, 0) => TextRange];
impl TextRange {
pub const fn new(start: TextIndex, end: TextIndex) -> Self {
assert!(start.0 <= end.0, "TextRange requires start <= end");
Self { start, end }
}
pub const fn from_prim(start: TextUnit, end: TextUnit) -> Self {
Self::new(TextIndex(start), TextIndex(end))
}
pub const fn from_start_len(start: TextIndex, len: TextUnit) -> Option<Self> {
match start.0.checked_add(len) {
Some(end) => Some(Self { start, end: TextIndex(end) }),
None => None,
}
}
pub const fn is_empty(self) -> bool {
self.start.0 == self.end.0
}
pub const fn len(self) -> TextUnit {
self.end.0 - self.start.0
}
}