1use super::*;
11use crate::data::*;
12use crate::handles::*;
13use crate::variant::*;
14use super::in_inclusive_range16;
16
17enum EucJpPending {
18 None,
19 Jis0208Lead(u8),
20 Jis0212Shift,
21 Jis0212Lead(u8),
22 HalfWidthKatakana,
23}
24
25impl EucJpPending {
26 fn is_none(&self) -> bool {
27 matches!(*self, EucJpPending::None)
28 }
29
30 fn count(&self) -> usize {
31 match *self {
32 EucJpPending::None => 0,
33 EucJpPending::Jis0208Lead(_)
34 | EucJpPending::Jis0212Shift
35 | EucJpPending::HalfWidthKatakana => 1,
36 EucJpPending::Jis0212Lead(_) => 2,
37 }
38 }
39}
40
41pub struct EucJpDecoder {
42 pending: EucJpPending,
43}
44
45impl EucJpDecoder {
46 pub fn new() -> VariantDecoder {
47 VariantDecoder::EucJp(EucJpDecoder {
48 pending: EucJpPending::None,
49 })
50 }
51
52 pub fn in_neutral_state(&self) -> bool {
53 self.pending.is_none()
54 }
55
56 fn plus_one_if_lead(&self, byte_length: usize) -> Option<usize> {
57 byte_length.checked_add(if self.pending.is_none() { 0 } else { 1 })
58 }
59
60 pub fn max_utf16_buffer_length(&self, byte_length: usize) -> Option<usize> {
61 self.plus_one_if_lead(byte_length)
62 }
63
64 pub fn max_utf8_buffer_length_without_replacement(&self, byte_length: usize) -> Option<usize> {
65 let len = self.plus_one_if_lead(byte_length);
67 checked_add(2, checked_add_opt(len, checked_div(checked_add(1, len), 2)))
68 }
69
70 pub fn max_utf8_buffer_length(&self, byte_length: usize) -> Option<usize> {
71 checked_mul(3, self.plus_one_if_lead(byte_length))
72 }
73
74 euc_jp_decoder_functions!(
75 {
76 let trail_minus_offset = byte.wrapping_sub(0xA1);
77 if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 {
80 handle.write_upper_bmp(0x3041 + u16::from(trail_minus_offset))
82 } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 {
83 handle.write_upper_bmp(0x30A1 + u16::from(trail_minus_offset))
85 } else if trail_minus_offset > (0xFE - 0xA1) {
86 if byte < 0x80 {
87 return (
88 DecoderResult::Malformed(1, 0),
89 unread_handle_trail.unread(),
90 handle.written(),
91 );
92 }
93 return (
94 DecoderResult::Malformed(2, 0),
95 unread_handle_trail.consumed(),
96 handle.written(),
97 );
98 } else {
99 let pointer = mul_94(jis0208_lead_minus_offset) + usize::from(trail_minus_offset);
100 let level1_pointer = pointer.wrapping_sub(1410);
101 if level1_pointer < JIS0208_LEVEL1_KANJI.len() {
102 handle.write_upper_bmp(JIS0208_LEVEL1_KANJI[level1_pointer])
103 } else {
104 let level2_pointer = pointer.wrapping_sub(4418);
105 if level2_pointer < JIS0208_LEVEL2_AND_ADDITIONAL_KANJI.len() {
106 handle.write_upper_bmp(JIS0208_LEVEL2_AND_ADDITIONAL_KANJI[level2_pointer])
107 } else {
108 let ibm_pointer = pointer.wrapping_sub(8272);
109 if ibm_pointer < IBM_KANJI.len() {
110 handle.write_upper_bmp(IBM_KANJI[ibm_pointer])
111 } else if let Some(bmp) = jis0208_symbol_decode(pointer) {
112 handle.write_bmp_excl_ascii(bmp)
113 } else if let Some(bmp) = jis0208_range_decode(pointer) {
114 handle.write_bmp_excl_ascii(bmp)
115 } else {
116 return (
117 DecoderResult::Malformed(2, 0),
118 unread_handle_trail.consumed(),
119 handle.written(),
120 );
121 }
122 }
123 }
124 }
125 },
126 {
127 let jis0212_lead_minus_offset = lead.wrapping_sub(0xA1);
130 if jis0212_lead_minus_offset > (0xFE - 0xA1) {
131 if lead < 0x80 {
132 return (
133 DecoderResult::Malformed(1, 0),
134 unread_handle_jis0212.unread(),
135 handle.written(),
136 );
137 }
138 return (
139 DecoderResult::Malformed(2, 0),
140 unread_handle_jis0212.consumed(),
141 handle.written(),
142 );
143 }
144 jis0212_lead_minus_offset
145 },
146 {
147 let trail_minus_offset = byte.wrapping_sub(0xA1);
150 if trail_minus_offset > (0xFE - 0xA1) {
151 if byte < 0x80 {
152 return (
153 DecoderResult::Malformed(2, 0),
154 unread_handle_trail.unread(),
155 handle.written(),
156 );
157 }
158 return (
159 DecoderResult::Malformed(3, 0),
160 unread_handle_trail.consumed(),
161 handle.written(),
162 );
163 }
164 let pointer = mul_94(jis0212_lead_minus_offset) + usize::from(trail_minus_offset);
165 let pointer_minus_kanji = pointer.wrapping_sub(1410);
166 if pointer_minus_kanji < JIS0212_KANJI.len() {
167 handle.write_upper_bmp(JIS0212_KANJI[pointer_minus_kanji])
168 } else if let Some(bmp) = jis0212_accented_decode(pointer) {
169 handle.write_bmp_excl_ascii(bmp)
170 } else {
171 let pointer_minus_upper_cyrillic = pointer.wrapping_sub(597);
172 if pointer_minus_upper_cyrillic <= (607 - 597) {
173 handle.write_mid_bmp(0x0402 + pointer_minus_upper_cyrillic as u16)
174 } else {
175 let pointer_minus_lower_cyrillic = pointer.wrapping_sub(645);
176 if pointer_minus_lower_cyrillic <= (655 - 645) {
177 handle.write_mid_bmp(0x0452 + pointer_minus_lower_cyrillic as u16)
178 } else {
179 return (
180 DecoderResult::Malformed(3, 0),
181 unread_handle_trail.consumed(),
182 handle.written(),
183 );
184 }
185 }
186 }
187 },
188 {
189 let trail_minus_offset = byte.wrapping_sub(0xA1);
192 if trail_minus_offset > (0xDF - 0xA1) {
193 if byte < 0x80 {
194 return (
195 DecoderResult::Malformed(1, 0),
196 unread_handle_trail.unread(),
197 handle.written(),
198 );
199 }
200 return (
201 DecoderResult::Malformed(2, 0),
202 unread_handle_trail.consumed(),
203 handle.written(),
204 );
205 }
206 handle.write_upper_bmp(0xFF61 + u16::from(trail_minus_offset))
207 },
208 self,
209 non_ascii,
210 jis0208_lead_minus_offset,
211 byte,
212 unread_handle_trail,
213 jis0212_lead_minus_offset,
214 lead,
215 unread_handle_jis0212,
216 source,
217 handle
218 );
219}
220
221#[cfg(feature = "fast-kanji-encode")]
222#[inline(always)]
223fn encode_kanji(bmp: u16) -> Option<(u8, u8)> {
224 jis0208_kanji_euc_jp_encode(bmp)
225}
226
227#[cfg(not(feature = "fast-kanji-encode"))]
228#[inline(always)]
229fn encode_kanji(bmp: u16) -> Option<(u8, u8)> {
230 if 0x4EDD == bmp {
231 Some((0xA1, 0xB8))
233 } else if let Some((lead, trail)) = jis0208_level1_kanji_euc_jp_encode(bmp) {
234 Some((lead, trail))
235 } else if let Some(pos) = jis0208_level2_and_additional_kanji_encode(bmp) {
236 let lead = (pos / 94) + 0xD0;
237 let trail = (pos % 94) + 0xA1;
238 Some((lead as u8, trail as u8))
239 } else if let Some(pos) = position(&IBM_KANJI[..], bmp) {
240 let lead = (pos / 94) + 0xF9;
241 let trail = (pos % 94) + 0xA1;
242 Some((lead as u8, trail as u8))
243 } else {
244 None
245 }
246}
247
248pub struct EucJpEncoder;
249
250impl EucJpEncoder {
251 pub fn new(encoding: &'static Encoding) -> Encoder {
252 Encoder::new(encoding, VariantEncoder::EucJp(EucJpEncoder))
253 }
254
255 pub fn max_buffer_length_from_utf16_without_replacement(
256 &self,
257 u16_length: usize,
258 ) -> Option<usize> {
259 u16_length.checked_mul(2)
260 }
261
262 pub fn max_buffer_length_from_utf8_without_replacement(
263 &self,
264 byte_length: usize,
265 ) -> Option<usize> {
266 byte_length.checked_add(1)
267 }
268
269 ascii_compatible_bmp_encoder_functions!(
270 {
271 let bmp_minus_hiragana = bmp.wrapping_sub(0x3041);
273 if bmp_minus_hiragana < 0x53 {
274 handle.write_two(0xA4, 0xA1 + bmp_minus_hiragana as u8)
275 } else if in_inclusive_range16(bmp, 0x4E00, 0x9FA0) {
276 if let Some((lead, trail)) = encode_kanji(bmp) {
277 handle.write_two(lead, trail)
278 } else {
279 return (
280 EncoderResult::unmappable_from_bmp(bmp),
281 source.consumed(),
282 handle.written(),
283 );
284 }
285 } else {
286 let bmp_minus_katakana = bmp.wrapping_sub(0x30A1);
287 if bmp_minus_katakana < 0x56 {
288 handle.write_two(0xA5, 0xA1 + bmp_minus_katakana as u8)
289 } else {
290 let bmp_minus_space = bmp.wrapping_sub(0x3000);
291 if bmp_minus_space < 3 {
292 handle.write_two(0xA1, 0xA1 + bmp_minus_space as u8)
294 } else if bmp == 0xA5 {
295 handle.write_one(0x5Cu8)
296 } else if bmp == 0x203E {
297 handle.write_one(0x7Eu8)
298 } else if in_inclusive_range16(bmp, 0xFF61, 0xFF9F) {
299 handle.write_two(0x8Eu8, (bmp - (0xFF61 - 0xA1)) as u8)
300 } else if bmp == 0x2212 {
301 handle.write_two(0xA1u8, 0xDDu8)
302 } else if let Some(pointer) = jis0208_range_encode(bmp) {
303 let lead = (pointer / 94) + 0xA1;
304 let trail = (pointer % 94) + 0xA1;
305 handle.write_two(lead as u8, trail as u8)
306 } else if in_inclusive_range16(bmp, 0xFA0E, 0xFA2D)
307 || bmp == 0xF929
308 || bmp == 0xF9DC
309 {
310 let pos = position(&IBM_KANJI[..], bmp).unwrap();
312 let lead = (pos / 94) + 0xF9;
313 let trail = (pos % 94) + 0xA1;
314 handle.write_two(lead as u8, trail as u8)
315 } else if let Some(pointer) = ibm_symbol_encode(bmp) {
316 let lead = (pointer / 94) + 0xA1;
317 let trail = (pointer % 94) + 0xA1;
318 handle.write_two(lead as u8, trail as u8)
319 } else if let Some(pointer) = jis0208_symbol_encode(bmp) {
320 let lead = (pointer / 94) + 0xA1;
321 let trail = (pointer % 94) + 0xA1;
322 handle.write_two(lead as u8, trail as u8)
323 } else {
324 return (
325 EncoderResult::unmappable_from_bmp(bmp),
326 source.consumed(),
327 handle.written(),
328 );
329 }
330 }
331 }
332 },
333 bmp,
334 self,
335 source,
336 handle,
337 copy_ascii_to_check_space_two,
338 check_space_two,
339 false
340 );
341}
342
343#[cfg(all(test, feature = "alloc"))]
347mod tests {
348 use super::super::testing::*;
349 use super::super::*;
350
351 fn decode_euc_jp(bytes: &[u8], expect: &str) {
352 decode(EUC_JP, bytes, expect);
353 }
354
355 fn encode_euc_jp(string: &str, expect: &[u8]) {
356 encode(EUC_JP, string, expect);
357 }
358
359 #[test]
360 fn test_euc_jp_decode() {
361 decode_euc_jp(b"", &"");
363
364 decode_euc_jp(b"\x61\x62", "\u{0061}\u{0062}");
366
367 decode_euc_jp(b"\x8E\xA1", "\u{FF61}");
369 decode_euc_jp(b"\x8E\xDF", "\u{FF9F}");
370 decode_euc_jp(b"\x8E\xA0", "\u{FFFD}");
371 decode_euc_jp(b"\x8E\xE0", "\u{FFFD}");
372 decode_euc_jp(b"\x8E\xFF", "\u{FFFD}");
373 decode_euc_jp(b"\x8E", "\u{FFFD}");
374
375 decode_euc_jp(b"\x8F\xA1\xA1", "\u{FFFD}");
377 decode_euc_jp(b"\x8F\xA2\xAF", "\u{02D8}");
378 decode_euc_jp(b"\x8F\xA2\xFF", "\u{FFFD}");
379 decode_euc_jp(b"\x8F\xA1", "\u{FFFD}");
380 decode_euc_jp(b"\x8F", "\u{FFFD}");
381
382 decode_euc_jp(b"\xA1\xA1", "\u{3000}");
384 decode_euc_jp(b"\xA1\xA0", "\u{FFFD}");
385 decode_euc_jp(b"\xFC\xFE", "\u{FF02}");
386 decode_euc_jp(b"\xFE\xFE", "\u{FFFD}");
387 decode_euc_jp(b"\xA1", "\u{FFFD}");
388
389 decode_euc_jp(b"\xFF\xA1\xA1", "\u{FFFD}\u{3000}");
391 decode_euc_jp(b"\xA0\xA1\xA1", "\u{FFFD}\u{3000}");
392 decode_euc_jp(b"\x80\xA1\xA1", "\u{FFFD}\u{3000}");
393 decode_euc_jp(b"\x81\xA1\xA1", "\u{FFFD}\u{3000}");
394 decode_euc_jp(b"\x82\xA1\xA1", "\u{FFFD}\u{3000}");
395 decode_euc_jp(b"\x83\xA1\xA1", "\u{FFFD}\u{3000}");
396 decode_euc_jp(b"\x84\xA1\xA1", "\u{FFFD}\u{3000}");
397 decode_euc_jp(b"\x85\xA1\xA1", "\u{FFFD}\u{3000}");
398 decode_euc_jp(b"\x86\xA1\xA1", "\u{FFFD}\u{3000}");
399 decode_euc_jp(b"\x87\xA1\xA1", "\u{FFFD}\u{3000}");
400 decode_euc_jp(b"\x88\xA1\xA1", "\u{FFFD}\u{3000}");
401 decode_euc_jp(b"\x89\xA1\xA1", "\u{FFFD}\u{3000}");
402 decode_euc_jp(b"\x8A\xA1\xA1", "\u{FFFD}\u{3000}");
403 decode_euc_jp(b"\x8B\xA1\xA1", "\u{FFFD}\u{3000}");
404 decode_euc_jp(b"\x8C\xA1\xA1", "\u{FFFD}\u{3000}");
405 decode_euc_jp(b"\x8D\xA1\xA1", "\u{FFFD}\u{3000}");
406
407 decode_euc_jp(b"\xA1\x40", "\u{FFFD}\u{0040}");
409 }
410
411 #[test]
412 fn test_euc_jp_encode() {
413 encode_euc_jp("", b"");
415
416 encode_euc_jp("\u{0061}\u{0062}", b"\x61\x62");
418
419 encode_euc_jp("\u{00A5}", b"\x5C");
421 encode_euc_jp("\u{203E}", b"\x7E");
422 encode_euc_jp("\u{2212}", b"\xA1\xDD");
423
424 encode_euc_jp("\u{FF61}", b"\x8E\xA1");
426 encode_euc_jp("\u{FF9F}", b"\x8E\xDF");
427
428 encode_euc_jp("\u{02D8}", b"˘");
430
431 encode_euc_jp("\u{3000}", b"\xA1\xA1");
433 encode_euc_jp("\u{FF02}", b"\xFC\xFE");
434 }
435}