use crate::{
compare,
convert::{self, AsciiCase, TextBuf},
encoding::{Codepoints, Encoding, codepoints},
grapheme::{
Grapheme, GraphemeIndices as IndexedGraphemes, Graphemes,
StrGraphemeIndices as StrIndexedGraphemes, StrGraphemes, grapheme_indices,
grapheme_indices_str, graphemes, graphemes_str,
},
truncate::{
skip_columns, skip_columns_str, truncate, truncate_measured, truncate_measured_str,
truncate_str,
},
unit::Unit,
utf8::Utf8,
utf16::Utf16,
utf32::Utf32,
width::{width, width_str, width_within, width_within_str},
wrap::{
StrWrapped, Wrapped, WrappedLine, WrappedMeasured as MeasuredWrapped, wrap, wrap_measured,
wrap_measured_str, wrap_str,
},
};
pub trait Text {
type Encoding: Encoding;
type Cluster<'a>: Copy
where
Self: 'a;
type Graphemes<'a>: DoubleEndedIterator<Item = Self::Cluster<'a>> + ExactSizeIterator + Clone
where
Self: 'a;
type GraphemeIndices<'a>: DoubleEndedIterator<Item = (usize, Self::Cluster<'a>)>
+ ExactSizeIterator
+ Clone
where
Self: 'a;
type Wrapped<'a>: Iterator<Item = &'a Self> + Clone
where
Self: 'a;
type WrappedMeasured<'a>: Iterator<Item = WrappedLine<'a, Self::Encoding>> + Clone
where
Self: 'a;
fn graphemes(&self) -> Self::Graphemes<'_>;
fn grapheme_indices(&self) -> Self::GraphemeIndices<'_>;
fn codepoints(&self) -> Codepoints<'_, Self::Encoding>;
fn visible_width(&self) -> usize;
fn width_within(&self, max_width: usize) -> Option<usize>;
fn truncate_width(&self, max_width: usize) -> &Self;
fn truncate_measured(&self, max_width: usize) -> (&Self, usize);
fn skip_columns(&self, columns: usize) -> (&Self, usize);
fn wrap(&self, max_width: usize) -> Self::Wrapped<'_>;
fn wrap_measured(&self, max_width: usize) -> Self::WrappedMeasured<'_>;
fn as_units(&self) -> &[<Self::Encoding as Encoding>::Unit];
#[inline]
fn transcode<C: TextBuf>(&self) -> C {
C::from_units(convert::transcode::<Self::Encoding, <C::Unit as Unit>::Native>(
self.as_units(),
))
}
#[inline]
fn transcode_into<U: Unit>(&self, dst: &mut [U]) -> (usize, usize) {
convert::transcode_into::<Self::Encoding, U::Native>(
self.as_units(),
dst,
AsciiCase::Preserve,
)
}
#[inline]
fn transcoded_len<U: Unit>(&self) -> usize {
convert::transcoded_len::<Self::Encoding, U::Native>(self.as_units())
}
#[inline]
fn eq_text<U: Unit>(&self, other: impl AsRef<[U]>) -> bool {
compare::equals::<Self::Encoding, U::Native>(self.as_units(), other.as_ref())
}
#[inline]
fn eq_text_ignore_ascii_case<U: Unit>(&self, other: impl AsRef<[U]>) -> bool {
compare::equals_ignore_ascii_case::<Self::Encoding, U::Native>(
self.as_units(),
other.as_ref(),
)
}
}
impl Text for str {
type Cluster<'a> = &'a Self;
type Encoding = Utf8;
type GraphemeIndices<'a> = StrIndexedGraphemes<'a>;
type Graphemes<'a> = StrGraphemes<'a>;
type Wrapped<'a> = StrWrapped<'a>;
type WrappedMeasured<'a> = MeasuredWrapped<'a, Utf8>;
#[inline]
fn graphemes(&self) -> StrGraphemes<'_> {
graphemes_str(self)
}
#[inline]
fn grapheme_indices(&self) -> Self::GraphemeIndices<'_> {
grapheme_indices_str(self)
}
#[inline]
fn codepoints(&self) -> Codepoints<'_, Utf8> {
codepoints::<Utf8>(self.as_bytes())
}
#[inline]
fn visible_width(&self) -> usize {
width_str(self)
}
#[inline]
fn width_within(&self, max_width: usize) -> Option<usize> {
width_within_str(self, max_width)
}
#[inline]
fn truncate_width(&self, max_width: usize) -> &Self {
truncate_str(self, max_width)
}
#[inline]
fn truncate_measured(&self, max_width: usize) -> (&Self, usize) {
truncate_measured_str(self, max_width)
}
#[inline]
fn skip_columns(&self, columns: usize) -> (&Self, usize) {
skip_columns_str(self, columns)
}
#[inline]
fn wrap(&self, max_width: usize) -> StrWrapped<'_> {
wrap_str(self, max_width)
}
#[inline]
fn wrap_measured(&self, max_width: usize) -> Self::WrappedMeasured<'_> {
wrap_measured_str(self, max_width)
}
#[inline]
fn as_units(&self) -> &[u8] {
self.as_bytes()
}
}
macro_rules! impl_text_for_units {
($unit:ty, $encoding:ty) => {
impl Text for [$unit] {
type Cluster<'a> = Grapheme<'a, $encoding>;
type Encoding = $encoding;
type GraphemeIndices<'a> = IndexedGraphemes<'a, $encoding>;
type Graphemes<'a> = Graphemes<'a, $encoding>;
type Wrapped<'a> = Wrapped<'a, $encoding>;
type WrappedMeasured<'a> = MeasuredWrapped<'a, $encoding>;
#[inline]
fn graphemes(&self) -> Graphemes<'_, $encoding> {
graphemes::<$encoding>(self)
}
#[inline]
fn grapheme_indices(&self) -> Self::GraphemeIndices<'_> {
grapheme_indices::<$encoding>(self)
}
#[inline]
fn codepoints(&self) -> Codepoints<'_, $encoding> {
codepoints::<$encoding>(self)
}
#[inline]
fn visible_width(&self) -> usize {
width::<$encoding>(self)
}
#[inline]
fn width_within(&self, max_width: usize) -> Option<usize> {
width_within::<$encoding>(self, max_width)
}
#[inline]
fn truncate_width(&self, max_width: usize) -> &[$unit] {
truncate::<$encoding>(self, max_width)
}
#[inline]
fn truncate_measured(&self, max_width: usize) -> (&[$unit], usize) {
truncate_measured::<$encoding>(self, max_width)
}
#[inline]
fn skip_columns(&self, columns: usize) -> (&[$unit], usize) {
skip_columns::<$encoding>(self, columns)
}
#[inline]
fn wrap(&self, max_width: usize) -> Wrapped<'_, $encoding> {
wrap::<$encoding>(self, max_width)
}
#[inline]
fn wrap_measured(&self, max_width: usize) -> Self::WrappedMeasured<'_> {
wrap_measured::<$encoding>(self, max_width)
}
#[inline]
fn as_units(&self) -> &[$unit] {
self
}
}
};
}
impl_text_for_units!(u8, Utf8);
impl_text_for_units!(u16, Utf16<false>);
impl_text_for_units!(u32, Utf32<false>);