use super::SegIndex;
use crate::{ByteIndex, ColIndex, ColWidth, Length, usize};
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
pub type SegmentArray = Vec<Seg>;
#[derive(Copy, Clone, Default, PartialEq, Ord, PartialOrd, Eq, Hash)]
pub struct Seg {
pub start_byte_index: ByteIndex,
pub end_byte_index: ByteIndex,
pub display_width: ColWidth,
pub seg_index: SegIndex,
pub bytes_size: Length,
pub start_display_col_index: ColIndex,
}
impl Debug for Seg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Seg[{s_i:>2}] โ โ โก byte: [{b_b:>2}, {b_e:>2}] size: {b_s} โ disp โฎผ col({d_i:>2}) โ width({d_w:>2}) โ",
s_i = **self.seg_index,
b_b = *self.start_byte_index,
b_e = *self.end_byte_index,
b_s = self.bytes_size.as_usize(),
d_i = **self.start_display_col_index,
d_w = **self.display_width,
)
}
}
impl Display for Seg {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "Seg[{}]", **self.seg_index)
}
}
impl Seg {
pub fn get_str<'a>(&self, arg_str: &'a (impl AsRef<str> + ?Sized)) -> &'a str {
let str = arg_str.as_ref();
let start_index = usize(self.start_byte_index);
let end_index = usize(self.end_byte_index);
&str[start_index..end_index]
}
}
#[cfg(test)]
mod tests {
use crate::{GCStringOwned, byte_index, col, seg_index, width};
#[test]
fn test_single_grapheme_cluster() {
let grapheme_string: GCStringOwned = "๐ฆ".into();
if let Some(segment) = grapheme_string.segments.first() {
assert_eq!(segment.start_byte_index, byte_index(0));
assert_eq!(segment.end_byte_index, byte_index(4));
assert_eq!(segment.display_width, width(2));
assert_eq!(segment.seg_index, seg_index(0));
assert_eq!(segment.bytes_size.as_usize(), 4);
assert_eq!(segment.start_display_col_index, col(0));
assert_eq!(segment.get_str(&grapheme_string), "๐ฆ");
}
}
#[test]
fn test_multiple_grapheme_clusters() {
let grapheme_string: GCStringOwned = "๐ฆ๐๐ฝ".into();
assert_eq!(grapheme_string.segments.len(), 2);
let segment1 = &grapheme_string.segments[0];
assert_eq!(segment1.start_byte_index, byte_index(0));
assert_eq!(segment1.end_byte_index, byte_index(4));
assert_eq!(segment1.display_width, width(2));
assert_eq!(segment1.seg_index, seg_index(0));
assert_eq!(segment1.bytes_size.as_usize(), 4);
assert_eq!(segment1.start_display_col_index, col(0));
assert_eq!(segment1.get_str(&grapheme_string), "๐ฆ");
let segment2 = &grapheme_string.segments[1];
assert_eq!(segment2.start_byte_index, byte_index(4));
assert_eq!(segment2.end_byte_index, byte_index(12));
assert_eq!(segment2.display_width, width(2));
assert_eq!(segment2.seg_index, seg_index(1));
assert_eq!(segment2.bytes_size.as_usize(), 8);
assert_eq!(segment2.start_display_col_index, col(2));
assert_eq!(segment2.get_str(&grapheme_string), "๐๐ฝ");
}
#[test]
#[allow(clippy::unicode_not_nfc)] fn test_combining_grapheme_cluster() {
let grapheme_string: GCStringOwned = "aฬ".into(); if let Some(segment) = grapheme_string.segments.first() {
assert_eq!(segment.start_byte_index, byte_index(0));
assert_eq!(segment.end_byte_index, byte_index(3));
assert_eq!(segment.display_width, width(1));
assert_eq!(segment.seg_index, seg_index(0));
assert_eq!(segment.bytes_size.as_usize(), 3);
assert_eq!(segment.start_display_col_index, col(0));
assert_eq!(segment.get_str(&grapheme_string), "aฬ");
}
}
#[test]
fn test_seg_str() {
let grapheme_string: GCStringOwned = "๐ฆ๐๐ฝ".into();
if let Some(segment) = grapheme_string.segments.first() {
assert_eq!(segment.get_str(&grapheme_string), "๐ฆ");
}
}
}