use alloc::string::{String, ToString};
use core::fmt;
#[cfg(feature = "traits")]
pub use crate::traits::truncate::Truncation;
#[derive(Debug)]
#[must_use]
pub struct Truncate<T> {
length: usize,
data: T,
suffix: Option<String>,
}
impl<T> Truncate<T> {
pub fn new(data: T, length: usize) -> Self {
Self {
length,
data,
suffix: None,
}
}
pub fn with_suffix(self, suffix: impl fmt::Display) -> Self {
Self {
suffix: Some(suffix.to_string()),
..self
}
}
}
impl<T: fmt::Display> fmt::Display for Truncate<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let truncated = &self
.data
.to_string()
.chars()
.take(if let Some(ref suffix) = self.suffix {
self.length - suffix.len()
} else {
self.length
})
.collect::<String>();
truncated.fmt(f)?;
if let Some(ref suffix) = self.suffix {
suffix.fmt(f)?;
}
Ok(())
}
}
#[must_use]
#[deprecated = "This is no longer used internally, and was never intended to be used externally"]
pub struct TruncatedFormatter<'a> {
remaining: usize,
writer: &'a mut fmt::Formatter<'a>,
}
#[allow(deprecated)]
impl<'a> TruncatedFormatter<'a> {
pub fn new(writer: &'a mut fmt::Formatter<'a>, length: usize) -> Self {
Self {
remaining: length,
writer,
}
}
}
#[allow(deprecated)]
impl fmt::Write for TruncatedFormatter<'_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
if self.remaining < s.len() {
self.writer.write_str(&s[0..self.remaining])?;
self.remaining = 0;
Ok(())
} else {
self.remaining -= s.len();
self.writer.write_str(s)
}
}
}
#[cfg(test)]
mod tests {
use super::Truncate;
#[test]
fn test_with_suffix() {
let suffixed = Truncate::new("Hello, World!", 8).with_suffix("...");
assert_eq!("Hello...", suffixed.to_string());
}
#[test]
fn test_with_padding() {
let truncated = Truncate::new("Hello, World!", 5);
let padded = format!("{truncated:<10}");
assert_eq!("Hello ", padded);
}
#[test]
fn test_longer_length_than_string() {
let truncated = Truncate::new("Hey", 15);
assert_eq!("Hey", truncated.to_string());
}
}