#![cfg_attr(not(test), no_std)]
use core::fmt;
extern crate alloc;
use alloc::{vec, vec::Vec, string::String};
#[derive(Debug, Clone)]
pub struct DecodeError {
codepoint: char,
index: usize,
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} at index {} is not part of the alphabet",
self.codepoint, self.index
)
}
}
pub type Alphabet = [char; 256];
pub trait Base {
const ALPHABET: Alphabet;
fn get_index(c: char) -> Option<u8>;
fn decode(input: &str) -> Result<Vec<u8>, DecodeError> {
let s = input.chars().count();
let mut output = vec![0; s];
for (i, c) in input.chars().enumerate() {
output[i] = Self::get_index(c).ok_or(DecodeError {
codepoint: c,
index: i,
})?;
}
Ok(output)
}
fn encode(input: &[u8]) -> String {
let s = input
.iter()
.map(|&x| Self::ALPHABET[x as usize].len_utf8())
.sum();
let mut output: Vec<u8> = vec![0; s];
let mut i = 0;
for &v in input.iter() {
let c = Self::ALPHABET[v as usize];
c.encode_utf8(&mut output[i..]);
i += c.len_utf8();
}
String::from_utf8(output).unwrap()
}
}
#[derive(Debug, Default)]
pub struct Emoji;
macro_rules! gen_alphabet {
($name:ident, $alphabet:literal) => {
impl Base for $name {
const ALPHABET: Alphabet = const_str::to_char_array!($alphabet);
fn get_index(c: char) -> Option<u8> {
match_lookup::gen_char_match!(c, $alphabet).map(|c| c as u8)
}
}
};
}
gen_alphabet!(Emoji, "๐๐ชโ๐ฐ๐๐๐๐๐๐๐๐๐๐๐๐๐โ๐ป๐ฅ๐พ๐ฟ๐โค๐๐คฃ๐๐๐๐ญ๐๐๐
๐๐๐ฅ๐ฅฐ๐๐๐๐ข๐ค๐๐๐ช๐โบ๐๐ค๐๐๐๐๐น๐คฆ๐๐โโจ๐คท๐ฑ๐๐ธ๐๐๐๐๐๐๐๐๐คฉ๐๐๐ค๐๐ฏ๐๐๐ถ๐๐คญโฃ๐๐๐๐ช๐๐ฅ๐๐๐ฉ๐ก๐คช๐๐ฅณ๐ฅ๐คค๐๐๐ณโ๐๐๐ด๐๐ฌ๐๐๐ท๐ป๐โญโ
๐ฅบ๐๐๐ค๐ฆโ๐ฃ๐๐โน๐๐๐ โ๐๐บ๐๐ป๐๐๐๐๐น๐ฃ๐ซ๐๐๐ต๐ค๐๐ด๐ค๐ผ๐ซโฝ๐คโ๐๐คซ๐๐ฎ๐๐ป๐๐ถ๐๐ฒ๐ฟ๐งก๐โก๐๐โโ๐๐ฐ๐คจ๐ถ๐ค๐ถ๐ฐ๐๐ข๐ค๐๐จ๐จ๐คฌโ๐๐บ๐ค๐๐๐ฑ๐๐ถ๐ฅดโถโกโ๐๐ธโฌ๐จ๐๐ฆ๐ท๐บโ ๐
๐๐ต๐๐คฒ๐ค ๐คง๐๐ต๐
๐ง๐พ๐๐๐ค๐๐คฏ๐ทโ๐ง๐ฏ๐๐๐ค๐๐โ๐ด๐ฃ๐ธ๐๐๐ฅ๐คข๐
๐ก๐ฉ๐๐ธ๐ป๐ค๐คฎ๐ผ๐ฅต๐ฉ๐๐๐ผ๐๐ฃ๐ฅ");
#[cfg(test)]
mod tests {
use crate::{Base, Emoji};
extern crate alloc;
use alloc::vec;
#[test]
fn byte1_rt() {
let mut org = vec![0u8; 1];
for i in 0..255 {
org[0] = i;
let e = Emoji::encode(&org);
let r = match Emoji::decode(e.as_str()) {
Ok(x) => x,
Err(e) => {
panic!("{}", e);
}
};
assert_eq!(org, r)
}
}
#[test]
fn index() {
for (i, &c) in Emoji::ALPHABET.iter().enumerate() {
println!("i{}:{}, {:?}", i, c, Emoji::get_index(c));
assert!(i as u8 == Emoji::get_index(c).unwrap());
}
}
#[test]
fn juan() {
let hi = "hi juan!";
let encoded = Emoji::encode(&hi.as_bytes().to_owned());
assert_eq!("๐ด๐๐
๐ฌ๐ค๐คค๐ป๐", encoded);
println!("{}: {}", hi, encoded);
}
#[test]
fn reference() {
let hi = "yes mani !";
let encoded = Emoji::encode(&hi.as_bytes().to_owned());
assert_eq!("๐โ๐๐
๐ท๐คค๐ป๐๐
๐", encoded);
println!("{}: {}", hi, encoded);
}
}