1use super::{Format, Modifier, Result, Style, Write};
2use crate::io::Counter;
3
4#[allow(missing_docs)]
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Dir {
8 Left,
9 Center,
10 Right,
11}
12super::derive!(
13 enum Dir {
14 Left,
15 Center,
16 Right,
17 }
18);
19
20#[allow(missing_docs)]
22#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub enum Kind {
24 #[default]
26 Full,
27
28 Mod,
30}
31super::derive!(
32 enum Kind {
33 Full,
34 Mod,
35 }
36);
37
38#[derive(Clone, Copy, PartialEq, Eq)]
41pub struct Pad<S> {
42 pub align: Dir,
44
45 pub with: char,
47
48 pub count: usize,
50
51 pub kind: Kind,
53
54 pub style: S,
56}
57super::derive!(struct Pad<S!> { align, with, count, kind, style });
58
59impl<S: Style> Pad<S> {
60 pub const fn left(with: char, count: usize, style: S) -> Self {
64 Self {
65 align: Dir::Left,
66 with,
67 count,
68 kind: Kind::Full,
69 style,
70 }
71 }
72
73 pub const fn center(with: char, count: usize, style: S) -> Self {
77 Self {
78 align: Dir::Center,
79 with,
80 count,
81 kind: Kind::Full,
82 style,
83 }
84 }
85
86 pub const fn right(with: char, count: usize, style: S) -> Self {
90 Self {
91 align: Dir::Right,
92 with,
93 count,
94 kind: Kind::Full,
95 style,
96 }
97 }
98
99 pub const fn left_mod(with: char, count: usize, style: S) -> Self {
103 Self {
104 align: Dir::Left,
105 with,
106 count,
107 kind: Kind::Mod,
108 style,
109 }
110 }
111
112 pub const fn center_mod(with: char, count: usize, style: S) -> Self {
116 Self {
117 align: Dir::Center,
118 with,
119 count,
120 kind: Kind::Mod,
121 style,
122 }
123 }
124
125 pub const fn right_mod(with: char, count: usize, style: S) -> Self {
129 Self {
130 align: Dir::Right,
131 with,
132 count,
133 kind: Kind::Mod,
134 style,
135 }
136 }
137}
138
139impl<S: Style> Style for Pad<S> {}
140
141impl<S: Style> Modifier for Pad<S> {
142 type Inner = S;
143
144 fn apply<T>(&self, f: &mut dyn Write, data: &T) -> Result
145 where
146 T: Format<S> + ?Sized,
147 {
148 let mut counter = Counter::new();
149 data.fmt(&mut counter, &self.style)?;
150
151 let chs = match self.kind {
152 Kind::Full => self.count.saturating_sub(counter.0),
153 Kind::Mod => self.count - counter.0.checked_rem(self.count).unwrap_or(0),
154 };
155
156 match self.align {
157 Dir::Left => {
158 data.fmt(f, &self.style)?;
159 for _ in 0..chs {
160 f.write_char(self.with)?;
161 }
162 }
163 Dir::Center => {
164 let before = chs / 2;
165 let after = chs.div_ceil(2);
166
167 for _ in 0..before {
168 f.write_char(self.with)?;
169 }
170 data.fmt(f, &self.style)?;
171 for _ in 0..after {
172 f.write_char(self.with)?;
173 }
174 }
175 Dir::Right => {
176 for _ in 0..chs {
177 f.write_char(self.with)?;
178 }
179 data.fmt(f, &self.style)?;
180 }
181 }
182
183 Ok(())
184 }
185}