1#![cfg_attr(not(test), no_std)]
2
3use core::fmt;
4extern crate alloc;
5use alloc::{vec, vec::Vec, string::String};
6
7#[derive(Debug, Clone)]
8pub struct DecodeError {
9 codepoint: char,
10 index: usize,
11}
12
13impl fmt::Display for DecodeError {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 write!(
16 f,
17 "{} at index {} is not part of the alphabet",
18 self.codepoint, self.index
19 )
20 }
21}
22
23pub type Alphabet = [char; 256];
24
25pub trait Base {
26 const ALPHABET: Alphabet;
27
28 fn get_index(c: char) -> Option<u8>;
29
30 fn decode(input: &str) -> Result<Vec<u8>, DecodeError> {
31 let s = input.chars().count();
32 let mut output = vec![0; s];
33 for (i, c) in input.chars().enumerate() {
34 output[i] = Self::get_index(c).ok_or(DecodeError {
35 codepoint: c,
36 index: i,
37 })?;
38 }
39
40 Ok(output)
41 }
42
43 fn encode(input: &[u8]) -> String {
44 let s = input
45 .iter()
46 .map(|&x| Self::ALPHABET[x as usize].len_utf8())
47 .sum();
48 let mut output: Vec<u8> = vec![0; s];
49 let mut i = 0;
50 for &v in input.iter() {
51 let c = Self::ALPHABET[v as usize];
52 c.encode_utf8(&mut output[i..]);
53 i += c.len_utf8();
54 }
55
56 String::from_utf8(output).unwrap()
57 }
58}
59
60#[derive(Debug, Default)]
61pub struct Emoji;
62
63macro_rules! gen_alphabet {
64 ($name:ident, $alphabet:literal) => {
65 impl Base for $name {
66 const ALPHABET: Alphabet = const_str::to_char_array!($alphabet);
67
68 fn get_index(c: char) -> Option<u8> {
69 match_lookup::gen_char_match!(c, $alphabet).map(|c| c as u8)
70 }
71 }
72 };
73}
74
75gen_alphabet!(Emoji, "๐๐ชโ๐ฐ๐๐๐๐๐๐๐๐๐๐๐๐๐โ๐ป๐ฅ๐พ๐ฟ๐โค๐๐คฃ๐๐๐๐ญ๐๐๐
๐๐๐ฅ๐ฅฐ๐๐๐๐ข๐ค๐๐๐ช๐โบ๐๐ค๐๐๐๐๐น๐คฆ๐๐โโจ๐คท๐ฑ๐๐ธ๐๐๐๐๐๐๐๐๐คฉ๐๐๐ค๐๐ฏ๐๐๐ถ๐๐คญโฃ๐๐๐๐ช๐๐ฅ๐๐๐ฉ๐ก๐คช๐๐ฅณ๐ฅ๐คค๐๐๐ณโ๐๐๐ด๐๐ฌ๐๐๐ท๐ป๐โญโ
๐ฅบ๐๐๐ค๐ฆโ๐ฃ๐๐โน๐๐๐ โ๐๐บ๐๐ป๐๐๐๐๐น๐ฃ๐ซ๐๐๐ต๐ค๐๐ด๐ค๐ผ๐ซโฝ๐คโ๐๐คซ๐๐ฎ๐๐ป๐๐ถ๐๐ฒ๐ฟ๐งก๐โก๐๐โโ๐๐ฐ๐คจ๐ถ๐ค๐ถ๐ฐ๐๐ข๐ค๐๐จ๐จ๐คฌโ๐๐บ๐ค๐๐๐ฑ๐๐ถ๐ฅดโถโกโ๐๐ธโฌ๐จ๐๐ฆ๐ท๐บโ ๐
๐๐ต๐๐คฒ๐ค ๐คง๐๐ต๐
๐ง๐พ๐๐๐ค๐๐คฏ๐ทโ๐ง๐ฏ๐๐๐ค๐๐โ๐ด๐ฃ๐ธ๐๐๐ฅ๐คข๐
๐ก๐ฉ๐๐ธ๐ป๐ค๐คฎ๐ผ๐ฅต๐ฉ๐๐๐ผ๐๐ฃ๐ฅ");
76
77#[cfg(test)]
78mod tests {
79 use crate::{Base, Emoji};
80
81 extern crate alloc;
82 use alloc::vec;
83
84 #[test]
85 fn byte1_rt() {
86 let mut org = vec![0u8; 1];
87 for i in 0..255 {
88 org[0] = i;
89 let e = Emoji::encode(&org);
90 let r = match Emoji::decode(e.as_str()) {
91 Ok(x) => x,
92 Err(e) => {
93 panic!("{}", e);
94 }
95 };
96 assert_eq!(org, r)
97 }
98 }
99
100 #[test]
101 fn index() {
102 for (i, &c) in Emoji::ALPHABET.iter().enumerate() {
103 println!("i{}:{}, {:?}", i, c, Emoji::get_index(c));
104 assert!(i as u8 == Emoji::get_index(c).unwrap());
105 }
106 }
107
108 #[test]
109 fn juan() {
110 let hi = "hi juan!";
111 let encoded = Emoji::encode(&hi.as_bytes().to_owned());
112 assert_eq!("๐ด๐๐
๐ฌ๐ค๐คค๐ป๐", encoded);
113 println!("{}: {}", hi, encoded);
114 }
115
116 #[test]
117 fn reference() {
118 let hi = "yes mani !";
119 let encoded = Emoji::encode(&hi.as_bytes().to_owned());
120 assert_eq!("๐โ๐๐
๐ท๐คค๐ป๐๐
๐", encoded);
121 println!("{}: {}", hi, encoded);
122 }
123}