1use std::io::Write;
2
3use crate::{
4 ENCODE_FALLBACK,
5 Textcode,
6 write_ascii,
7 write_utf8,
8};
9
10fn decode_inner<W: Write>(src: &[u8], dst: &mut W, map: &[u16]) -> std::io::Result<usize> {
11 let mut written = 0;
12
13 for &c in src {
14 if c <= 0x7F {
15 written += write_ascii(dst, c)?;
16 } else if c >= 0xA0 {
17 let offset = c as usize - 0xA0;
18 let u = map[offset] as u32;
19 written += write_utf8(dst, u)?;
20 }
21 }
22
23 Ok(written)
24}
25
26fn encode_inner<W: Write>(
27 src: &str,
28 dst: &mut W,
29 hi_map: &[usize],
30 map: &[u8],
31) -> std::io::Result<usize> {
32 let mut written = 0;
33
34 for ch in src.chars() {
35 let u = u32::from(ch) as u16;
36 let c;
37
38 if u <= 0x7F {
39 c = u as u8;
40 } else if u >= 0xA0 {
41 let hi = usize::from(u >> 8);
42 let lo = usize::from(u & 0xFF);
43
44 let pos = hi_map[hi] * 0x100 + lo;
45 let code = map[pos];
46
47 if code != 0x0000 {
48 c = code;
49 } else {
50 c = ENCODE_FALLBACK;
51 }
52 } else {
53 c = ENCODE_FALLBACK;
54 }
55
56 dst.write_all(&[c])?;
57 written += 1;
58 }
59
60 Ok(written)
61}
62
63macro_rules! iso8859 {
64 ( $($struct_name: ident, $decode_map: ident, $hi_map: ident, $encode_map: ident),* ) => {
65 $(
66 pub struct $struct_name;
68
69 impl Textcode for $struct_name {
70 fn decode<W: Write, R: AsRef<[u8]>>(src: R, dst: &mut W) -> std::io::Result<usize> {
71 decode_inner(src.as_ref(), dst, &crate::data::$decode_map)
72 }
73
74 fn encode<W: Write, R: AsRef<str>>(src: R, dst: &mut W) -> std::io::Result<usize> {
75 encode_inner(src.as_ref(), dst, &crate::data::$hi_map, &crate::data::$encode_map)
76 }
77 }
78 )*
79 }
80}
81
82iso8859!(
83 Iso8859_1,
85 DECODE_MAP_1,
86 HI_MAP_1,
87 ENCODE_MAP_1,
88 Iso8859_2,
90 DECODE_MAP_2,
91 HI_MAP_2,
92 ENCODE_MAP_2,
93 Iso8859_3,
95 DECODE_MAP_3,
96 HI_MAP_3,
97 ENCODE_MAP_3,
98 Iso8859_4,
100 DECODE_MAP_4,
101 HI_MAP_4,
102 ENCODE_MAP_4,
103 Iso8859_5,
105 DECODE_MAP_5,
106 HI_MAP_5,
107 ENCODE_MAP_5,
108 Iso8859_6,
110 DECODE_MAP_6,
111 HI_MAP_6,
112 ENCODE_MAP_6,
113 Iso8859_7,
115 DECODE_MAP_7,
116 HI_MAP_7,
117 ENCODE_MAP_7,
118 Iso8859_8,
120 DECODE_MAP_8,
121 HI_MAP_8,
122 ENCODE_MAP_8,
123 Iso8859_9,
125 DECODE_MAP_9,
126 HI_MAP_9,
127 ENCODE_MAP_9,
128 Iso8859_10,
130 DECODE_MAP_10,
131 HI_MAP_10,
132 ENCODE_MAP_10,
133 Iso8859_11,
135 DECODE_MAP_11,
136 HI_MAP_11,
137 ENCODE_MAP_11,
138 Iso8859_13,
140 DECODE_MAP_13,
141 HI_MAP_13,
142 ENCODE_MAP_13,
143 Iso8859_14,
145 DECODE_MAP_14,
146 HI_MAP_14,
147 ENCODE_MAP_14,
148 Iso8859_15,
150 DECODE_MAP_15,
151 HI_MAP_15,
152 ENCODE_MAP_15,
153 Iso8859_16,
155 DECODE_MAP_16,
156 HI_MAP_16,
157 ENCODE_MAP_16
158);