1#![cfg_attr(not(feature = "std"), no_std)]
25
26#[cfg(not(feature = "std"))]
27extern crate alloc;
28
29pub mod alphabet;
30mod bigint;
31pub mod decoder;
32pub mod encoder;
33
34pub use alphabet::Alphabet;
35
36#[cfg(not(feature = "std"))]
37use alloc::{string::String, vec::Vec};
38
39#[cfg(not(feature = "std"))]
40use core as std;
41
42use std::fmt;
43
44#[derive(Debug)]
45pub struct DecodeError;
46
47impl fmt::Display for DecodeError {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 write!(f, "Failed to decode the given data")
50 }
51}
52
53#[cfg(feature = "std")]
54impl std::error::Error for DecodeError {}
55
56pub fn encode<A: Alphabet>(alphabet: A, input: &[u8]) -> String {
58 alphabet.encode(input)
59}
60
61pub fn decode<A: Alphabet>(alphabet: A, input: &str) -> Result<Vec<u8>, DecodeError> {
63 alphabet.decode(input)
64}
65
66#[cfg(test)]
67mod test {
68 use super::decode;
69 use super::encode;
70 use std::fs::File;
71 use std::io::Read;
72
73 #[test]
74 fn works() {
75 let mut file = File::open("./fixtures/fixtures.json").unwrap();
76 let mut data = String::new();
77 file.read_to_string(&mut data).unwrap();
78
79 let json: serde_json::Value = serde_json::from_str(&data).unwrap();
80 let alphabets = &json["alphabets"];
81
82 for value in json["valid"].as_array().unwrap() {
83 let alphabet_name = value["alphabet"].as_str().unwrap();
84 let input = value["string"].as_str().unwrap();
85 let alphabet = alphabets[alphabet_name].as_str().unwrap();
86
87 let decoded = decode(alphabet, input).unwrap();
89 let encoded = encode(alphabet, &decoded);
90 assert_eq!(encoded, input);
91
92 let decoded = decode(alphabet.as_bytes(), input).unwrap();
94 let encoded = encode(alphabet.as_bytes(), &decoded);
95 assert_eq!(encoded, input);
96 }
97 }
98
99 #[test]
100 fn is_unicode_sound() {
101 let alphabet = "😐😀";
103
104 let encoded = encode(alphabet, &[0xff, 0x00, 0xff, 0x00]);
105 let decoded = decode(alphabet, &encoded).unwrap();
106
107 assert_eq!(
108 encoded,
109 "😀😀😀😀😀😀😀😀😐😐😐😐😐😐😐😐😀😀😀😀😀😀😀😀😐😐😐😐😐😐😐😐"
110 );
111 assert_eq!(decoded, &[0xff, 0x00, 0xff, 0x00]);
112 }
113
114 #[test]
115 #[should_panic(expected = "at least 2")]
116 fn encode_empty_alphabet_panics() {
117 encode("", &[1u8]);
118 }
119
120 #[test]
121 #[should_panic(expected = "at least 2")]
122 fn encode_empty_alphabet_bytes_panics() {
123 encode(b"".as_slice(), &[1u8]);
124 }
125
126 #[test]
127 #[should_panic(expected = "at least 2")]
128 fn encode_single_char_alphabet_panics() {
129 encode("x", &[1u8]);
130 }
131
132 #[test]
133 #[should_panic(expected = "at least 2")]
134 fn encode_single_char_alphabet_bytes_panics() {
135 encode(b"x".as_slice(), &[1u8]);
136 }
137
138 #[test]
139 #[should_panic(expected = "duplicate")]
140 fn encode_duplicate_alphabet_panics() {
141 encode("aab", &[3u8]);
142 }
143
144 #[test]
145 #[should_panic(expected = "duplicate")]
146 fn encode_duplicate_alphabet_bytes_panics() {
147 encode(b"aab".as_slice(), &[3u8]);
148 }
149
150 #[test]
151 fn decode_empty_alphabet_returns_error() {
152 assert!(decode("", "abc").is_err());
153 }
154
155 #[test]
156 #[should_panic(expected = "duplicate")]
157 fn decode_duplicate_alphabet_panics() {
158 let _ = decode("aab", "aa");
159 }
160
161 #[test]
162 #[should_panic(expected = "duplicate")]
163 fn decode_duplicate_alphabet_bytes_panics() {
164 let _ = decode(b"aab".as_slice(), "aa");
165 }
166}