base256emoji/
lib.rs

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}