use crate::string::ShallowString;
use alloc::{
borrow::Cow,
format,
string::{String, ToString},
};
use core::fmt::Debug;
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct CharacterShallow {
pub max_width: usize,
pub end_reserved: usize,
pub shallow: ShallowMode,
pub counter: CounterMode,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum CounterMode {
Bytes,
Characters,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum ShallowMode {
PlaceHolder {
text: Cow<'static, str>,
},
Counter {
lhs: Cow<'static, str>,
rhs: Cow<'static, str>,
},
}
impl CounterMode {
pub fn count(&self, raw: &str) -> usize {
match self {
CounterMode::Bytes => raw.len(),
CounterMode::Characters => raw.chars().count(),
}
}
}
impl ShallowMode {
pub fn size_hint(&self, counter: CounterMode, fill: &str) -> usize {
match self {
ShallowMode::PlaceHolder { text } => counter.count(text),
ShallowMode::Counter { lhs, rhs } => {
let start = counter.count(lhs);
let middle = counter.count(fill);
let end = counter.count(rhs);
start + middle + end
}
}
}
pub fn make_string(&self, fill: &str) -> String {
match self {
ShallowMode::PlaceHolder { text } => text.to_string(),
ShallowMode::Counter { lhs, rhs } => format!("{lhs}{fill}{rhs}"),
}
}
}
impl Default for CharacterShallow {
fn default() -> Self {
Self {
max_width: 144,
end_reserved: 42,
shallow: ShallowMode::PlaceHolder { text: Cow::Borrowed(" <...> ") },
counter: CounterMode::Bytes,
}
}
}
impl CharacterShallow {
pub fn new(width: usize, reversed: usize) -> Self {
Self { max_width: width, end_reserved: reversed, ..Self::default() }
}
pub fn with_width(mut self, width: usize) -> Self {
self.max_width = width;
self
}
pub fn set_delta_width(&mut self, delta: isize) {
let new = if delta >= 0 {
self.max_width.saturating_add(delta as usize)
}
else {
self.max_width.saturating_sub(delta.abs() as usize)
};
self.max_width = new;
}
pub fn with_delta_width(mut self, delta: isize) -> Self {
self.set_delta_width(delta);
self
}
pub fn with_shallow_text(mut self, text: &'static str) -> Self {
self.shallow = ShallowMode::PlaceHolder { text: Cow::Borrowed(text) };
self
}
pub fn with_end_reserved(mut self, width: usize) -> Self {
self.end_reserved = width;
self
}
pub fn build<'s>(&self, raw: &'s str) -> ShallowString<'s> {
if raw.len() <= self.max_width {
return ShallowString { raw: Cow::Borrowed(raw) };
}
let mut string = String::with_capacity(self.max_width);
let start_len = self.max_width - self.end_reserved - self.shallow.size_hint(self.counter, &"fill");
unsafe {
let start = raw.get_unchecked(..start_len);
let middle = self.shallow.make_string("0");
let end = raw.get_unchecked(raw.len() - self.end_reserved..);
string.push_str(start);
string.push_str(middle.as_str());
string.push_str(end);
}
ShallowString { raw: Cow::Owned(string) }
}
pub fn build_cow<'s>(&self, raw: &'s str) -> Cow<'s, str> {
self.build(raw).raw
}
}