use smallvec::SmallVec;
use std::borrow::Cow;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Span {
pub start: usize,
pub end: usize,
}
impl Span {
#[inline]
pub const fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
#[inline]
pub const fn offset(self, delta: usize) -> Self {
Self {
start: self.start + delta,
end: self.end + delta,
}
}
}
impl std::fmt::Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Segment<'a> {
pub tag: &'a str,
pub span: Span,
pub tag_span: Span,
pub elements: Vec<Element<'a>>,
}
impl<'a> Segment<'a> {
#[inline]
pub fn new(tag: &'a str, elements: Vec<Element<'a>>) -> Self {
Self {
tag,
span: Span::default(),
tag_span: Span::default(),
elements,
}
}
#[inline]
pub fn get_element(&self, n: usize) -> Option<&Element<'a>> {
self.elements.get(n)
}
#[inline]
pub fn element_str(&self, n: usize) -> Option<&str> {
self.elements.get(n)?.get_component(0)
}
#[inline]
pub fn element_span(&self, n: usize) -> Option<Span> {
Some(self.elements.get(n)?.span)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element<'a> {
pub span: Span,
pub components: SmallVec<[Cow<'a, str>; 4]>,
pub component_spans: SmallVec<[Span; 4]>,
}
impl<'a> Element<'a> {
#[inline]
pub fn get_component(&self, n: usize) -> Option<&str> {
self.components.get(n).map(|c| c.as_ref())
}
#[inline]
pub fn component_or_empty(&self, n: usize) -> &str {
self.components.get(n).map(|c| c.as_ref()).unwrap_or("")
}
#[inline]
pub fn component_span(&self, n: usize) -> Option<Span> {
self.component_spans.get(n).copied()
}
pub fn of(components: &[&'a str]) -> Self {
Self {
span: Span::default(),
components: components.iter().copied().map(Cow::Borrowed).collect(),
component_spans: std::iter::repeat_n(Span::default(), components.len()).collect(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OwnedElement {
pub span: Span,
pub components: SmallVec<[String; 4]>,
pub component_spans: SmallVec<[Span; 4]>,
}
impl OwnedElement {
#[inline]
pub fn as_borrowed(&self) -> Element<'_> {
Element {
span: self.span,
components: self
.components
.iter()
.map(|component| Cow::Borrowed(component.as_str()))
.collect(),
component_spans: self.component_spans.clone(),
}
}
#[inline]
pub fn offset(mut self, delta: usize) -> Self {
self.span = self.span.offset(delta);
for span in &mut self.component_spans {
*span = span.offset(delta);
}
self
}
}
impl<'a> From<Element<'a>> for OwnedElement {
fn from(value: Element<'a>) -> Self {
Self {
span: value.span,
components: value
.components
.into_iter()
.map(|component| component.into_owned())
.collect(),
component_spans: value.component_spans,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OwnedSegment {
pub tag: String,
pub span: Span,
pub tag_span: Span,
pub elements: Vec<OwnedElement>,
}
#[derive(Debug, Clone, Copy)]
pub struct BorrowedElement<'a>(pub(crate) &'a OwnedElement);
impl<'a> BorrowedElement<'a> {
#[inline]
pub fn get_component(&self, n: usize) -> Option<&'a str> {
self.0.components.get(n).map(|s| s.as_str())
}
#[inline]
pub fn component_or_empty(&self, n: usize) -> &'a str {
self.0.components.get(n).map(|s| s.as_str()).unwrap_or("")
}
#[inline]
pub fn component_span(&self, n: usize) -> Option<Span> {
self.0.component_spans.get(n).copied()
}
#[inline]
pub fn span(&self) -> Span {
self.0.span
}
#[inline]
pub fn len(&self) -> usize {
self.0.components.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.components.is_empty()
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &'a str> {
self.0.components.iter().map(|c| c.as_str())
}
}
#[derive(Debug, Clone, Copy)]
pub struct BorrowedSegment<'a>(pub(crate) &'a OwnedSegment);
impl<'a> BorrowedSegment<'a> {
#[inline]
pub fn tag(&self) -> &'a str {
&self.0.tag
}
#[inline]
pub fn span(&self) -> Span {
self.0.span
}
#[inline]
pub fn tag_span(&self) -> Span {
self.0.tag_span
}
#[inline]
pub fn get_element(&self, n: usize) -> Option<BorrowedElement<'a>> {
self.0.elements.get(n).map(BorrowedElement)
}
#[inline]
pub fn element_str(&self, n: usize) -> Option<&'a str> {
self.0.elements.get(n)?.components.first().map(|c| c.as_str())
}
#[inline]
pub fn element_span(&self, n: usize) -> Option<Span> {
Some(self.0.elements.get(n)?.span)
}
#[inline]
pub fn elements(&self) -> impl Iterator<Item = BorrowedElement<'a>> {
self.0.elements.iter().map(BorrowedElement)
}
}
impl OwnedSegment {
#[inline]
pub fn element_str(&self, n: usize) -> Option<&str> {
self.elements.get(n)?.components.first().map(|s| s.as_str())
}
#[inline]
pub fn component_str(&self, elem: usize, comp: usize) -> Option<&str> {
self.elements.get(elem)?.components.get(comp).map(|s| s.as_str())
}
#[inline]
pub fn offset(mut self, delta: usize) -> Self {
self.span = self.span.offset(delta);
self.tag_span = self.tag_span.offset(delta);
for element in &mut self.elements {
element.span = element.span.offset(delta);
for span in &mut element.component_spans {
*span = span.offset(delta);
}
}
self
}
#[inline]
pub fn as_borrowed(&self) -> Segment<'_> {
Segment {
tag: self.tag.as_str(),
span: self.span,
tag_span: self.tag_span,
elements: self
.elements
.iter()
.map(OwnedElement::as_borrowed)
.collect(),
}
}
#[inline]
pub fn borrow(&self) -> BorrowedSegment<'_> {
BorrowedSegment(self)
}
}
impl<'a> From<Segment<'a>> for OwnedSegment {
fn from(value: Segment<'a>) -> Self {
Self {
tag: value.tag.to_string(),
span: value.span,
tag_span: value.tag_span,
elements: value.elements.into_iter().map(OwnedElement::from).collect(),
}
}
}