1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use std::string::FromUtf16Error; use unicode_width::UnicodeWidthStr; #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] pub enum TextAlignment { Left, Right, } pub trait PadString { fn pad_left(&self, width: usize) -> String { self.pad(width, ' ', TextAlignment::Right) } fn pad_right(&self, width: usize) -> String { self.pad(width, ' ', TextAlignment::Left) } fn pad_left_with(&self, width: usize, character: char) -> String { self.pad(width, character, TextAlignment::Right) } fn pad_right_with(&self, width: usize, character: char) -> String { self.pad(width, character, TextAlignment::Left) } fn pad_to_width_with_alignment(&self, width: usize, alignment: TextAlignment) -> String { self.pad(width, ' ', alignment) } fn pad(&self, width: usize, character: char, alignment: TextAlignment) -> String; } impl PadString for str { fn pad(&self, width: usize, character: char, alignment: TextAlignment) -> String { let display_columns = UnicodeWidthStr::width(self); if display_columns >= width { self.to_string() } else { let required = width - display_columns; let mut string = String::with_capacity(self.len() + required); let (left, right) = match alignment { TextAlignment::Left => (0, required), TextAlignment::Right => (required, 0), }; (0..left).for_each(|_| string.push(character)); string.push_str(self); (0..right).for_each(|_| string.push(character)); string } } } pub fn to_utf16(string: &str) -> Vec<u16> { string.encode_utf16().collect() } pub fn to_utf16_null(string: &str) -> Vec<u16> { string.encode_utf16().chain(Some(0)).collect() } pub fn from_utf16(data: &[u16]) -> Result<String, FromUtf16Error> { String::from_utf16(data) } pub fn from_utf16_null(data: &[u16]) -> Result<String, FromUtf16Error> { let data = utf16_extent(data); String::from_utf16(data) } pub fn from_utf16_lossy(data: &[u16]) -> String { String::from_utf16_lossy(data) } pub fn from_utf16_lossy_null(data: &[u16]) -> String { let data = utf16_extent(data); String::from_utf16_lossy(data) } fn utf16_extent(data: &[u16]) -> &[u16] { let length = data.iter().position(|x| *x == 0).unwrap_or(data.len()); &data[..length] }