mod sealed {
pub trait Sealed {}
impl Sealed for char {}
impl Sealed for &str {}
impl Sealed for &String {}
impl Sealed for String {}
}
pub trait PadWith: sealed::Sealed {
fn pad_chars(&self) -> impl Iterator<Item = char> + '_;
}
impl PadWith for char {
fn pad_chars(&self) -> impl Iterator<Item = char> + '_ {
std::iter::repeat(*self)
}
}
impl PadWith for &str {
fn pad_chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars().cycle()
}
}
impl PadWith for &String {
fn pad_chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars().cycle()
}
}
impl PadWith for String {
fn pad_chars(&self) -> impl Iterator<Item = char> + '_ {
self.chars().cycle()
}
}
pub trait JsStrExt {
fn pad_start<P: PadWith>(&self, length: usize, pad: P) -> String;
fn pad_end<P: PadWith>(&self, length: usize, pad: P) -> String;
}
impl JsStrExt for str {
fn pad_start<P: PadWith>(&self, length: usize, pad: P) -> String {
let len = self.chars().count();
if len >= length {
return self.to_string();
}
let gap = length - len;
let mut result = String::with_capacity(self.len() + gap);
result.extend(pad.pad_chars().take(gap));
result.push_str(self);
result
}
fn pad_end<P: PadWith>(&self, length: usize, pad: P) -> String {
let len = self.chars().count();
if len >= length {
return self.to_string();
}
let gap = length - len;
let mut result = String::with_capacity(self.len() + gap);
result.push_str(self);
result.extend(pad.pad_chars().take(gap));
result
}
}
#[cfg(test)]
mod tests;