ratatui_core/text/
masked.rs1use alloc::borrow::Cow;
2use core::fmt;
3
4use crate::text::Text;
5
6#[derive(Default, Clone, Eq, PartialEq, Hash)]
26pub struct Masked<'a> {
27 inner: Cow<'a, str>,
28 mask_char: char,
29}
30
31impl<'a> Masked<'a> {
32 pub fn new(s: impl Into<Cow<'a, str>>, mask_char: char) -> Self {
33 Self {
34 inner: s.into(),
35 mask_char,
36 }
37 }
38
39 pub const fn mask_char(&self) -> char {
41 self.mask_char
42 }
43
44 pub fn value(&self) -> Cow<'a, str> {
46 self.inner.chars().map(|_| self.mask_char).collect()
47 }
48}
49
50impl fmt::Debug for Masked<'_> {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 fmt::Display::fmt(&self.inner, f)
55 }
56}
57
58impl fmt::Display for Masked<'_> {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 fmt::Display::fmt(&self.value(), f)
62 }
63}
64
65impl<'a> From<&'a Masked<'a>> for Cow<'a, str> {
66 fn from(masked: &'a Masked) -> Self {
67 masked.value()
68 }
69}
70
71impl<'a> From<Masked<'a>> for Cow<'a, str> {
72 fn from(masked: Masked<'a>) -> Self {
73 masked.value()
74 }
75}
76
77impl<'a> From<&'a Masked<'_>> for Text<'a> {
78 fn from(masked: &'a Masked) -> Self {
79 Text::raw(masked.value())
80 }
81}
82
83impl<'a> From<Masked<'a>> for Text<'a> {
84 fn from(masked: Masked<'a>) -> Self {
85 Text::raw(masked.value())
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use alloc::format;
92
93 use super::*;
94 use crate::text::Line;
95
96 #[test]
97 fn new() {
98 let masked = Masked::new("12345", 'x');
99 assert_eq!(masked.inner, "12345");
100 assert_eq!(masked.mask_char, 'x');
101 }
102
103 #[test]
104 fn value() {
105 let masked = Masked::new("12345", 'x');
106 assert_eq!(masked.value(), "xxxxx");
107 }
108
109 #[test]
110 fn mask_char() {
111 let masked = Masked::new("12345", 'x');
112 assert_eq!(masked.mask_char(), 'x');
113 }
114
115 #[test]
116 fn debug() {
117 let masked = Masked::new("12345", 'x');
118 assert_eq!(format!("{masked:?}"), "12345");
119 assert_eq!(format!("{masked:.3?}"), "123", "Debug truncates");
120 }
121
122 #[test]
123 fn display() {
124 let masked = Masked::new("12345", 'x');
125 assert_eq!(format!("{masked}"), "xxxxx");
126 assert_eq!(format!("{masked:.3}"), "xxx", "Display truncates");
127 }
128
129 #[test]
130 fn into_text() {
131 let masked = Masked::new("12345", 'x');
132
133 let text: Text = (&masked).into();
134 assert_eq!(text.lines, [Line::from("xxxxx")]);
135
136 let text: Text = masked.into();
137 assert_eq!(text.lines, [Line::from("xxxxx")]);
138 }
139
140 #[test]
141 fn into_cow() {
142 let masked = Masked::new("12345", 'x');
143 let cow: Cow<str> = (&masked).into();
144 assert_eq!(cow, "xxxxx");
145
146 let cow: Cow<str> = masked.into();
147 assert_eq!(cow, "xxxxx");
148 }
149}