1#[derive(Copy, Clone, Debug)]
2struct Break {
3 index: usize,
4 priority: usize,
5 space: bool,
6}
7pub struct HeaderFieldFormatter {
8 max_width: usize,
9 distinct_priorities: usize,
10 scores: Vec<usize>,
15 optim: Vec<Option<usize>>,
19 buffer: Vec<u8>,
20 breaks: Vec<Break>,
22}
23
24#[derive(Debug, Clone, Copy)]
25pub struct FormatError;
26
27impl HeaderFieldFormatter {
28 pub fn new(
29 max_width: usize,
30 distinct_priorities: usize,
31 initial_text: &[u8],
32 initial_break_priority: usize,
33 initial_text_space: bool,
34 ) -> Self {
35 let buffer = if initial_text_space {
36 let mut buffer = Vec::with_capacity(initial_text.len() + 1);
37 buffer.extend_from_slice(initial_text);
38 buffer.push(b' ');
39 buffer
40 } else {
41 initial_text.to_vec()
42 };
43 Self {
44 max_width,
45 distinct_priorities,
46 scores: vec![0; distinct_priorities],
47 optim: vec![None],
48 buffer,
49 breaks: vec![Break {
50 index: initial_text.len() + (initial_text_space as usize),
51 priority: initial_break_priority,
52 space: initial_text_space,
53 }],
54 }
55 }
56 pub fn push(&mut self, token: &[u8], priority: usize, space: bool) -> Result<(), FormatError> {
57 if priority >= self.distinct_priorities {
58 panic!()
59 }
60 if token.len() > self.avail(false) {
61 return Err(FormatError);
62 }
63 self.buffer.extend(token);
64 let pre_space_len = self.buffer.len();
65 if space {
66 self.buffer.push(b' ');
67 }
68 if pre_space_len <= self.avail(true) {
69 self.next_score(self.breaks.len());
72 self.optim.push(None);
73 } else {
74 assert!(
82 !self.breaks.is_empty(),
83 "Breaking after the field name is always possible"
84 );
85 let mut try_break_idx = self.breaks.len() - 1;
90 let mut best_score = self.score(try_break_idx).to_vec();
91 best_score[self.breaks[try_break_idx].priority] += 1;
92 let mut best_score_break_idx = try_break_idx;
93
94 while try_break_idx > 0 {
95 try_break_idx -= 1;
96 let r#break = self.breaks[try_break_idx];
97 let potential_line_width = pre_space_len - r#break.index;
98 if potential_line_width > self.avail(false) {
99 break;
100 }
101 let mut score = self.score(try_break_idx).to_vec();
102 score[self.breaks[try_break_idx].priority] += 1;
103 if &score < &best_score {
104 for i in 0..best_score.len() {
105 best_score[i] = score[i];
106 }
107 best_score_break_idx = try_break_idx;
108 }
109 }
110
111 let result_score = self.next_score(self.breaks.len());
112 for i in 0..best_score.len() {
113 result_score[i] = best_score[i];
114 }
115
116 self.optim.push(Some(best_score_break_idx));
117 }
118 self.breaks.push(Break {
119 index: self.buffer.len(),
120 priority,
121 space,
122 });
123 Ok(())
124 }
125
126 pub fn done(self, ret: &mut Vec<u8>) {
127 let mut cur_break_and_idx = match self.optim.last().unwrap() {
128 Some(break_idx) => Some((self.breaks[*break_idx], *break_idx)),
129 None => {
130 if self.breaks.last().unwrap().space {
131 ret.extend_from_slice(&self.buffer[0..self.buffer.len() - 1]);
132 ret.push(b'\r');
133 ret.push(b'\n');
134 } else {
135 ret.extend_from_slice(&self.buffer);
136 ret.push(b'\r');
137 ret.push(b'\n');
138 };
139 return;
140 }
141 };
142 let mut indices = vec![];
143 let mut to_process_r = self.buffer.len() - self.breaks.last().unwrap().space as usize;
144 while let Some((cur_break, cur_break_idx)) = cur_break_and_idx {
145 let r = to_process_r;
146 let l = cur_break.index;
147 indices.push((l, r));
148 to_process_r = l - cur_break.space as usize;
149 cur_break_and_idx = self.optim[cur_break_idx].map(|idx| (self.breaks[idx], idx));
150 }
151 indices.push((0, to_process_r));
152 let mut first = true;
153 for (l, r) in indices.iter().rev().copied() {
154 if !first {
155 ret.push(b' ');
156 }
157 first = false;
158 ret.extend_from_slice(&self.buffer[l..r]);
159 ret.push(b'\r');
160 ret.push(b'\n');
161 }
162 }
163
164 fn score(&self, n: usize) -> &[usize] {
165 let l = n * self.distinct_priorities;
166 let r = (n + 1) * self.distinct_priorities;
167 &self.scores[l..r]
168 }
169
170 fn next_score(&mut self, n: usize) -> &mut [usize] {
171 assert!(n * self.distinct_priorities == self.scores.len());
172 self.scores.resize((n + 1) * self.distinct_priorities, 0);
173 let l = n * self.distinct_priorities;
174 let r = (n + 1) * self.distinct_priorities;
175 &mut self.scores[l..r]
176 }
177
178 fn avail(&self, is_first: bool) -> usize {
180 self.max_width - ((!is_first) as usize) }
182}
183
184#[allow(dead_code)]
202fn main() {
203 use std::io::stdin;
204 use std::io::BufRead;
205
206 let mut hff = HeaderFieldFormatter::new(78, 3, b"To:", 2, true);
207 for line in stdin().lock().lines() {
208 let line = line.unwrap();
209 let chs = line.as_bytes();
210 let mut prio = 0;
211 let mut cursor = 0;
212 while chs[cursor].is_ascii_digit() {
213 prio *= 10;
214 prio += (chs[cursor] - b'0') as usize;
215 cursor += 1;
216 }
217
218 let space = match chs[cursor] {
219 b' ' => true,
220 b'!' => false,
221 _ => panic!("{}", line),
222 };
223
224 hff.push(&chs[cursor + 1..], prio, space).unwrap();
225 }
226 let mut result = vec![];
227 hff.done(&mut result);
228 print!("{}", std::str::from_utf8(&result).unwrap());
229}