use std::{
borrow::Cow,
ops::{Bound, RangeBounds},
};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Highlight<'text> {
pub line: usize,
pub offset: usize,
pub length: usize,
pub comment: Option<Cow<'text, str>>,
}
impl<'text> From<(usize, usize, usize)> for Highlight<'text> {
fn from(value: (usize, usize, usize)) -> Self {
Self {
line: value.0,
offset: value.1,
length: value.2,
comment: None,
}
}
}
impl<'text, Comment: Into<Cow<'text, str>>> From<(usize, usize, usize, Comment)>
for Highlight<'text>
{
fn from(value: (usize, usize, usize, Comment)) -> Self {
Self {
line: value.0,
offset: value.1,
length: value.2,
comment: Some(value.3.into()),
}
}
}
impl<'text, Range: RangeBounds<usize>> From<(usize, Range)> for Highlight<'text> {
fn from(value: (usize, Range)) -> Self {
let offset = match value.1.start_bound() {
Bound::Excluded(n) => n + 1,
Bound::Included(n) => *n,
Bound::Unbounded => 0,
};
Self {
line: value.0,
offset,
length: match value.1.end_bound() {
Bound::Excluded(n) => n.saturating_sub(offset),
Bound::Included(n) => n.saturating_sub(offset + 1),
Bound::Unbounded => usize::MAX,
},
comment: None,
}
}
}
impl<'text, Range: RangeBounds<usize>, Comment: Into<Cow<'text, str>>> From<(u64, Range, Comment)>
for Highlight<'text>
{
fn from(value: (u64, Range, Comment)) -> Self {
let offset = match value.1.start_bound() {
Bound::Excluded(n) => n + 1,
Bound::Included(n) => *n,
Bound::Unbounded => 0,
};
Self {
line: value.0 as usize,
offset,
length: match value.1.end_bound() {
Bound::Excluded(n) => n - offset,
Bound::Included(n) => n - offset + 1,
Bound::Unbounded => usize::MAX,
},
comment: Some(value.2.into()),
}
}
}
impl<'text> Highlight<'text> {
pub fn to_owned(self) -> Highlight<'static> {
Highlight {
comment: self.comment.map(|c| Cow::Owned(c.into_owned())),
..self
}
}
}