use std::fmt::{
self,
Write,
};
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Compound<'s> {
pub src: &'s str,
pub bold: bool,
pub italic: bool,
pub code: bool,
pub strikeout: bool,
}
impl<'s> Compound<'s> {
pub fn raw_str(src: &'s str) -> Compound<'s> {
Compound {
src,
bold: false,
italic: false,
code: false,
strikeout: false,
}
}
pub fn set_str(
&mut self,
src: &'s str,
) {
self.src = src;
}
pub fn set_attributes_from(
&mut self,
other: &Compound,
) {
self.bold = other.bold;
self.italic = other.italic;
self.code = other.code;
self.strikeout = other.strikeout;
}
pub fn sub(
&self,
r_start: usize,
r_end: usize,
) -> Compound<'s> {
Compound {
src: &self.src[r_start..r_end],
bold: self.bold,
italic: self.italic,
code: self.code,
strikeout: self.strikeout,
}
}
pub fn sub_chars(
&self,
r_start: usize,
r_end: usize,
) -> Compound<'s> {
let mut rb_start = 0;
let mut rb_end = 0;
for (char_idx, (byte_idx, _)) in self.as_str().char_indices().enumerate() {
if char_idx == r_start {
rb_start = byte_idx;
} else if char_idx == r_end {
rb_end = byte_idx;
break;
}
}
if rb_end == 0 && rb_start != 0 {
self.tail(rb_start)
} else {
self.sub(rb_start, rb_end)
}
}
pub fn tail(
&self,
r_start: usize,
) -> Compound<'s> {
Compound {
src: &self.src[r_start..],
bold: self.bold,
italic: self.italic,
code: self.code,
strikeout: self.strikeout,
}
}
pub fn tail_chars(
&self,
r_start: usize,
) -> Compound<'s> {
let mut rb_start = 0;
for (char_idx, (byte_idx, _)) in self.as_str().char_indices().enumerate() {
rb_start = byte_idx;
if char_idx == r_start {
break;
}
}
self.tail(rb_start)
}
pub fn cut_tail(
&mut self,
tail_size: usize,
) -> Compound<'s> {
let cut = self.src.len() - tail_size;
let tail = Compound {
src: &self.src[cut..],
bold: self.bold,
italic: self.italic,
code: self.code,
strikeout: self.strikeout,
};
self.src = &self.src[0..cut];
tail
}
pub fn raw_part(
src: &'s str,
start: usize,
end: usize,
) -> Compound<'s> {
Compound {
src: &src[start..end],
bold: false,
italic: false,
code: false,
strikeout: false,
}
}
pub fn new(
src: &'s str, start: usize, end: usize,
bold: bool,
italic: bool,
code: bool,
strikeout: bool,
) -> Compound<'s> {
Compound {
src: &src[start..end],
italic,
bold,
code,
strikeout,
}
}
pub fn bold(mut self) -> Compound<'s> {
self.bold = true;
self
}
pub fn italic(mut self) -> Compound<'s> {
self.italic = true;
self
}
pub fn code(mut self) -> Compound<'s> {
self.code = true;
self
}
pub fn strikeout(mut self) -> Compound<'s> {
self.strikeout = true;
self
}
pub fn set_bold(
&mut self,
bold: bool,
) {
self.bold = bold;
}
pub fn set_italic(
&mut self,
italic: bool,
) {
self.italic = italic;
}
pub fn set_code(
&mut self,
code: bool,
) {
self.code = code;
}
pub fn set_strikeout(
&mut self,
strikeout: bool,
) {
self.strikeout = strikeout;
}
pub fn as_str(&self) -> &'s str {
self.src
}
pub fn char_length(&self) -> usize {
self.as_str().chars().count()
}
pub fn is_empty(&self) -> bool {
self.src.is_empty()
}
}
impl fmt::Display for Compound<'_> {
fn fmt(
&self,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
f.write_str(self.as_str())?;
Ok(())
}
}
impl fmt::Debug for Compound<'_> {
fn fmt(
&self,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
if self.bold {
f.write_char('B')?;
}
if self.italic {
f.write_char('I')?;
}
if self.code {
f.write_char('C')?;
}
if self.strikeout {
f.write_char('S')?;
}
f.write_char('"')?;
f.write_str(self.as_str())?;
f.write_char('"')?;
Ok(())
}
}