1pub use super::decode;
6pub use encoding_types::{
7 ByteWriter, CodecError, DecoderTrap, DecoderTrapFunc, EncoderTrap, EncoderTrapFunc, Encoding,
8 EncodingRef, RawDecoder, RawEncoder, StringWriter,
9};
10
11#[cfg(test)]
12mod tests {
13 use super::EncoderTrap::NcrEscape;
14 use super::*;
15 use crate::util::StrCharIndex;
16 use std::convert::Into;
17 use std::sync::mpsc::channel;
18
19 struct MyEncoder {
23 flag: bool,
24 prohibit: char,
25 prepend: &'static str,
26 toggle: bool,
27 }
28 impl RawEncoder for MyEncoder {
29 fn from_self(&self) -> Box<dyn RawEncoder> {
30 Box::new(MyEncoder {
31 flag: self.flag,
32 prohibit: self.prohibit,
33 prepend: self.prepend,
34 toggle: false,
35 })
36 }
37 fn is_ascii_compatible(&self) -> bool {
38 self.flag
39 }
40 fn raw_feed(
41 &mut self,
42 input: &str,
43 output: &mut dyn ByteWriter,
44 ) -> (usize, Option<CodecError>) {
45 for ((i, j), ch) in input.index_iter() {
46 if ch <= '\u{7f}' && ch != self.prohibit {
47 if self.toggle && !self.prepend.is_empty() {
48 output.write_bytes(self.prepend.as_bytes());
49 }
50 output.write_byte(ch as u8);
51 if ch == 'e' {
52 self.toggle = !self.toggle;
53 }
54 } else {
55 return (
56 i,
57 Some(CodecError {
58 upto: j as isize,
59 cause: "!!!".into(),
60 }),
61 );
62 }
63 }
64 (input.len(), None)
65 }
66 fn raw_finish(&mut self, _output: &mut dyn ByteWriter) -> Option<CodecError> {
67 None
68 }
69 }
70
71 struct MyEncoding {
72 flag: bool,
73 prohibit: char,
74 prepend: &'static str,
75 }
76 impl Encoding for MyEncoding {
77 fn name(&self) -> &'static str {
78 "my encoding"
79 }
80 fn raw_encoder(&self) -> Box<dyn RawEncoder> {
81 Box::new(MyEncoder {
82 flag: self.flag,
83 prohibit: self.prohibit,
84 prepend: self.prepend,
85 toggle: false,
86 })
87 }
88 fn raw_decoder(&self) -> Box<dyn RawDecoder> {
89 panic!("not supported")
90 }
91 }
92
93 #[test]
94 fn test_encoding_debug_format() {
95 let enc = MyEncoding {
96 flag: true,
97 prohibit: '\u{80}',
98 prepend: "",
99 };
100
101 assert_eq!(
102 format!("{:?}", &enc as &dyn Encoding),
103 "Encoding(my encoding)"
104 );
105 }
106
107 #[test]
108 fn test_reencoding_trap_with_ascii_compatible_encoding() {
109 static COMPAT: &MyEncoding = &MyEncoding {
110 flag: true,
111 prohibit: '\u{80}',
112 prepend: "",
113 };
114 static INCOMPAT: &MyEncoding = &MyEncoding {
115 flag: false,
116 prohibit: '\u{80}',
117 prepend: "",
118 };
119
120 assert_eq!(
121 COMPAT.encode("Hello\u{203d} I'm fine.", NcrEscape),
122 Ok(b"Hello‽ I'm fine.".to_vec())
123 );
124 assert_eq!(
125 INCOMPAT.encode("Hello\u{203d} I'm fine.", NcrEscape),
126 Ok(b"Hello‽ I'm fine.".to_vec())
127 );
128 }
129
130 #[test]
131 fn test_reencoding_trap_with_ascii_incompatible_encoding() {
132 static COMPAT: &MyEncoding = &MyEncoding {
133 flag: true,
134 prohibit: '\u{80}',
135 prepend: "*",
136 };
137 static INCOMPAT: &MyEncoding = &MyEncoding {
138 flag: false,
139 prohibit: '\u{80}',
140 prepend: "*",
141 };
142
143 assert_eq!(
145 COMPAT.encode("Hello\u{203d} I'm fine.", NcrEscape),
146 Ok(b"He*l*l*o‽* *I*'*m* *f*i*n*e.".to_vec())
147 );
148 assert_eq!(
149 INCOMPAT.encode("Hello\u{203d} I'm fine.", NcrEscape),
150 Ok(b"He*l*l*o*&*#*8*2*5*3*;* *I*'*m* *f*i*n*e.".to_vec())
151 );
152 }
153
154 #[test]
155 fn test_encoding_sendable() {
156 static COMPAT: &MyEncoding = &MyEncoding {
157 flag: true,
158 prohibit: '\u{80}',
159 prepend: "*",
160 };
161 let encoder = COMPAT.raw_encoder();
162 let (tx, _rx) = channel();
163 let _ = tx.send(encoder);
164 }
165
166 #[test]
167 #[should_panic]
168 fn test_reencoding_trap_can_fail() {
169 static FAIL: &MyEncoding = &MyEncoding {
170 flag: false,
171 prohibit: '&',
172 prepend: "",
173 };
174
175 let _ = FAIL.encode("Hello\u{203d} I'm fine.", NcrEscape);
177 }
178}