1extern crate encoding_types;
11
12use encoding_types::*;
13use std::str::from_utf8;
14
15#[derive(Clone, Copy)]
16pub struct ROT13Encoding;
17
18impl Encoding for ROT13Encoding {
19 fn name(&self) -> &'static str {
20 "rot13"
21 }
22 fn whatwg_name(&self) -> Option<&'static str> {
23 None
24 }
25 fn raw_encoder(&self) -> Box<dyn RawEncoder> {
26 ROT13Encoder::new()
27 }
28 fn raw_decoder(&self) -> Box<dyn RawDecoder> {
29 ROT13Decoder::new()
30 }
31}
32
33#[derive(Clone, Copy)]
34pub struct ROT13Encoder;
35
36impl ROT13Encoder {
37 #[allow(clippy::new_ret_no_self)]
38 pub fn new() -> Box<dyn RawEncoder> {
39 Box::new(ROT13Encoder)
40 }
41}
42
43impl RawEncoder for ROT13Encoder {
44 fn from_self(&self) -> Box<dyn RawEncoder> {
45 ROT13Encoder::new()
46 }
47 fn is_ascii_compatible(&self) -> bool {
48 true
49 }
50
51 fn raw_feed(
52 &mut self,
53 input: &str,
54 output: &mut dyn ByteWriter,
55 ) -> (usize, Option<CodecError>) {
56 output.writer_hint(input.len());
57 for byte in input.bytes() {
58 output.write_byte(rotate_byte(byte))
59 }
60 (input.len(), None)
61 }
62
63 fn raw_finish(&mut self, _output: &mut dyn ByteWriter) -> Option<CodecError> {
64 None
65 }
66}
67
68#[derive(Clone, Copy)]
69pub struct ROT13Decoder;
70
71impl ROT13Decoder {
72 #[allow(clippy::new_ret_no_self)]
73 pub fn new() -> Box<dyn RawDecoder> {
74 Box::new(ROT13Decoder)
75 }
76}
77
78impl RawDecoder for ROT13Decoder {
79 fn from_self(&self) -> Box<dyn RawDecoder> {
80 ROT13Decoder::new()
81 }
82 fn is_ascii_compatible(&self) -> bool {
83 true
84 }
85
86 fn raw_feed(
87 &mut self,
88 input: &[u8],
89 output: &mut dyn StringWriter,
90 ) -> (usize, Option<CodecError>) {
91 output.writer_hint(input.len());
92 let string = match from_utf8(input) {
93 Ok(s) => s,
94 Err(_e) => {
95 return (
96 0,
97 Some(CodecError {
98 upto: 0, cause: "input is not valid utf-8".into(),
101 }),
102 );
103 }
104 };
105 for ch in string.chars() {
106 match ch {
107 'a'..='z' | 'A'..='Z' => output.write_char(rotate_byte(ch as u8) as char),
108 _ => output.write_char(ch),
109 }
110 }
111 (input.len(), None)
112 }
113
114 fn raw_finish(&mut self, _output: &mut dyn StringWriter) -> Option<CodecError> {
115 None
116 }
117}
118
119fn rotate_byte(byte: u8) -> u8 {
120 match byte {
121 b'a'..=b'm' | b'A'..=b'M' => byte + 13,
122 b'n'..=b'z' | b'N'..=b'Z' => byte - 13,
123 _ => byte,
124 }
125}
126
127fn main() {
128 use std::io;
129 use std::io::Read;
130
131 let mut ret = Vec::new();
132 io::stdin()
133 .read_to_end(&mut ret)
134 .expect("cannot read from the input");
135 match ROT13Encoding.decode(&ret, DecoderTrap::Strict) {
136 Ok(s) => println!("{}", s),
137 Err(e) => panic!("decoder error: {}", e),
138 };
139}