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
95
96
97
98
99
100
use std::io::{Result as IoResult, Write, Read};
pub fn owo_copy<R: Read, W: Write>(from: R, mut to: W) -> IoResult<()> {
let face_step = (&from as *const R as usize) % FACES.len();
let mut cur_face_idx = (&to as *const W as usize) % FACES.len();
let mut cur_state = State::None;
for b in from.bytes() {
handle_byte(b?, &mut to, face_step, &mut cur_face_idx, &mut cur_state)?;
}
Ok(())
}
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
enum State {
None,
HaveSmallN,
HaveBigN,
HaveOveO,
HaveOveV,
HaveExclamationMarks,
}
static FACES: &[&str] = &["(・`ω´・)", "OwO", "owo", "oωo", "òωó", "°ω°", "UwU", ">w<", "^w^"];
fn handle_byte<W: Write>(b: u8, to: &mut W, face_step: usize, cur_face_idx: &mut usize, cur_state: &mut State) -> IoResult<()> {
match (*cur_state, b) {
(State::None, c) if c == b'r' || c == b'l' => to.write_all(b"w")?,
(State::None, c) if c == b'R' || c == b'L' => to.write_all(b"W")?,
(State::None, b'n') => *cur_state = State::HaveSmallN,
(State::HaveSmallN, c) if c == b'a' || c == b'e' || c == b'i' || c == b'o' || c == b'u' => to.write_all(b"ny").and_then(|_| to.write_all(&[c]))?,
(State::HaveSmallN, c) => {
*cur_state = State::None;
to.write_all(&[b'n']).and_then(|_| handle_byte(c, to, face_step, cur_face_idx, cur_state))?
}
(State::None, b'N') => *cur_state = State::HaveBigN,
(State::HaveBigN, c) if c == b'a' || c == b'e' || c == b'i' || c == b'o' || c == b'u' => to.write_all(b"Ny").and_then(|_| to.write_all(&[c]))?,
(State::HaveBigN, c) if c == b'A' || c == b'E' || c == b'I' || c == b'O' || c == b'U' => to.write_all(b"NY").and_then(|_| to.write_all(&[c]))?,
(State::HaveBigN, c) => {
*cur_state = State::None;
to.write_all(b"N").and_then(|_| handle_byte(c, to, face_step, cur_face_idx, cur_state))?
}
(State::None, b'o') => *cur_state = State::HaveOveO,
(State::HaveOveO, b'v') => *cur_state = State::HaveOveV,
(State::HaveOveO, c) => {
*cur_state = State::None;
to.write_all(b"o").and_then(|_| handle_byte(c, to, face_step, cur_face_idx, cur_state))?
}
(State::HaveOveV, b'e') => {
*cur_state = State::None;
to.write_all(b"uv")?
}
(State::HaveOveV, c) => {
*cur_state = State::None;
to.write_all(b"ov").and_then(|_| handle_byte(c, to, face_step, cur_face_idx, cur_state))?
}
(s, b'!') if s == State::None || s == State::HaveExclamationMarks => *cur_state = State::HaveExclamationMarks,
(State::HaveExclamationMarks, c) => {
*cur_state = State::None;
to.write_all(b" ")
.and_then(|_| to.write_all(FACES[*cur_face_idx].as_bytes()))
.and_then(|_| to.write_all(b" "))
.and_then(|_| handle_byte(c, to, face_step, cur_face_idx, cur_state))?;
*cur_face_idx = (*cur_face_idx + face_step) % FACES.len();
}
(State::None, c) => to.write_all(&[c])?,
}
Ok(())
}