#![no_std]
#![doc = include_str!("../README.md")]
extern crate alloc;
use core::fmt::{Display, Write};
pub trait SliceDisplay<'a, T: Display> {
#[must_use = "this does not display the slice, \
it returns an object that can be displayed"]
fn display(&'a self) -> SliceDisplayImpl<'a, T>;
}
#[derive(Clone, Copy)]
pub struct SliceDisplayImpl<'a, T: Display> {
slice: &'a [T],
terminators: (char, char),
delimiter: char,
should_space: bool,
}
impl<'a, T: Display> SliceDisplayImpl<'a, T> {
pub fn terminator(self, beginning: char, ending: char) -> Self {
Self {
terminators: (beginning, ending),
..self
}
}
pub fn delimiter(self, delimiter: char) -> Self {
Self { delimiter, ..self }
}
pub fn should_space(self, should_space: bool) -> Self {
Self {
should_space,
..self
}
}
}
impl<T: Display, A> SliceDisplay<'_, T> for A
where
A: AsRef<[T]>,
{
fn display(&self) -> SliceDisplayImpl<'_, T> {
SliceDisplayImpl {
slice: self.as_ref(),
terminators: ('[', ']'),
delimiter: ',',
should_space: true,
}
}
}
impl<'a, T: Display> Display for SliceDisplayImpl<'a, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let (beginning, ending) = self.terminators;
let delimiter = self.delimiter;
let spacing = if self.should_space { " " } else { "" };
f.write_char(beginning)?;
if let Some((last, elems)) = self.slice.split_last() {
for elem in elems {
write!(f, "{elem}{delimiter}{spacing}")?;
}
write!(f, "{last}")?;
}
f.write_char(ending)
}
}
#[cfg(test)]
mod tests {
use alloc::{string::ToString, vec::Vec};
use crate::SliceDisplay;
extern crate alloc;
#[test]
fn slice_display_empty() {
let empty: Vec<u8> = Vec::new();
let empty_array: [u8; 0] = [];
let empty_slice: &[u8] = &[];
assert_eq!(empty.display().to_string(), "[]");
assert_eq!(empty_array.display().to_string(), "[]");
assert_eq!(empty_slice.display().to_string(), "[]");
}
#[test]
fn slice_display_single() {
let single = [1];
assert_eq!(single.display().to_string(), "[1]");
}
#[test]
fn slice_display_multiple() {
let numbers = [1, 2, 3, 4, 5];
assert_eq!(numbers.display().to_string(), "[1, 2, 3, 4, 5]");
}
#[test]
fn slice_display_custom_delimiter() {
let numbers = [1, 2, 3, 4, 5];
assert_eq!(
numbers.display().delimiter(';').to_string(),
"[1; 2; 3; 4; 5]"
);
assert_eq!(
numbers
.display()
.delimiter('-')
.should_space(false)
.to_string(),
"[1-2-3-4-5]"
);
}
#[test]
fn slice_display_custom_terminators() {
let numbers = [1, 2, 3, 4, 5];
assert_eq!(
numbers.display().terminator('{', '}').to_string(),
"{1, 2, 3, 4, 5}"
);
assert_eq!(
numbers
.display()
.terminator('{', '}')
.should_space(false)
.delimiter(';')
.to_string(),
"{1;2;3;4;5}"
);
}
}