1use std::collections::HashMap;
2
3#[derive(PartialEq, Eq, Hash, Clone, Copy)]
4pub enum PokeChar {
5 Print(char),
7 Term,
9 Unmapped,
10}
11
12impl PokeChar {
13 pub fn to_char(self) -> char {
14 if let PokeChar::Print(ch) = self {
15 ch
16 } else {
17 '?'
18 }
19 }
20}
21
22use PokeChar::Print as P;
23
24macro_rules! map {
25 ($($nv:expr => $pc:expr,)+) => {
26 thread_local! {
27 static POKECHAR_TO_ENCODED: HashMap<PokeChar, u8> = {
28 let mut map = HashMap::new();
29 $(
30 map.insert($pc, $nv);
31 )+
32 map
33 };
34 static ENCODED_TO_POKECHAR: HashMap<u8, PokeChar> = {
35 let mut map = HashMap::new();
36 $(
37 map.insert($nv, $pc);
38 )+
39 map
40 };
41 }
42 }
43}
44
45map! {
46 0x00 => P(' '),
47 0x05 => P('È'), 0x06 => P('É'), 0x1A => P('è'), 0x1B => P('é'),
48 0xA1 => P('0'), 0xA2 => P('1'), 0xA3 => P('2'), 0xA4 => P('3'), 0xA5 => P('4'),
49 0xA6 => P('5'), 0xA7 => P('6'), 0xA8 => P('7'), 0xA9 => P('8'), 0xAA => P('9'),
50 0xAB => P('!'), 0xAC => P('?'), 0xAD => P('.'), 0xAE => P('-'),
51 0xBB => P('A'), 0xBC => P('B'), 0xBD => P('C'), 0xBE => P('D'), 0xBF => P('E'),
52 0xC0 => P('F'), 0xC1 => P('G'), 0xC2 => P('H'), 0xC3 => P('I'), 0xC4 => P('J'),
53 0xC5 => P('K'), 0xC6 => P('L'), 0xC7 => P('M'), 0xC8 => P('N'), 0xC9 => P('O'),
54 0xCA => P('P'), 0xCB => P('Q'), 0xCC => P('R'), 0xCD => P('S'), 0xCE => P('T'),
55 0xCF => P('U'), 0xD0 => P('V'), 0xD1 => P('W'), 0xD2 => P('X'), 0xD3 => P('Y'),
56 0xD4 => P('Z'),
57 0xD5 => P('a'), 0xD6 => P('b'), 0xD7 => P('c'), 0xD8 => P('d'), 0xD9 => P('e'),
58 0xDA => P('f'), 0xDB => P('g'), 0xDC => P('h'), 0xDD => P('i'), 0xDE => P('j'),
59 0xDF => P('k'), 0xE0 => P('l'), 0xE1 => P('m'), 0xE2 => P('n'), 0xE3 => P('o'),
60 0xE4 => P('p'), 0xE5 => P('q'), 0xE6 => P('r'), 0xE7 => P('s'), 0xE8 => P('t'),
61 0xE9 => P('u'), 0xEA => P('v'), 0xEB => P('w'), 0xEC => P('x'), 0xED => P('y'),
62 0xEE => P('z'),
63 0xFF => PokeChar::Term,
64}
65
66pub fn decode_byte(value: u8) -> PokeChar {
67 ENCODED_TO_POKECHAR.with(|map| map.get(&value).cloned().unwrap_or(PokeChar::Unmapped))
68}
69
70pub fn decode_string(poke: &[u8]) -> String {
71 poke.iter().cloned().map(decode_byte).map(PokeChar::to_char).collect()
72}
73
74pub fn encode_string(src: &str, dst: &mut [u8]) {
75 let mut dst_bytes = dst.iter_mut();
76 for ch in src.chars().map(|ch| {
77 POKECHAR_TO_ENCODED.with(|map| map.get(&PokeChar::Print(ch)).cloned().expect("No mapping"))
78 }) {
79 *dst_bytes.next().unwrap() = ch;
80 }
81 while let Some(b) = dst_bytes.next() {
82 *b = 0xFF;
83 }
84}