base_x/
lib.rs

1//! # base_x
2//!
3//! Encode and decode any base alphabet.
4//!
5//! ## Installation
6//!
7//! Add this to `Cargo.toml` file:
8//!
9//! ```toml
10//! [dependencies]
11//! base-x = "0.2.0"
12//! ```
13//!
14//! ## Usage
15//!
16//! ```rust
17//! extern crate base_x;
18//!
19//! fn main() {
20//!   let decoded = base_x::decode("01", "11111111000000001111111100000000").unwrap();
21//!   let encoded = base_x::encode("01", &decoded);
22//!  assert_eq!(encoded, "11111111000000001111111100000000");
23//! }
24//! ```
25
26#![cfg_attr(not(feature = "std"), no_std)]
27
28#[cfg(not(feature = "std"))]
29extern crate alloc;
30
31pub mod alphabet;
32mod bigint;
33pub mod decoder;
34pub mod encoder;
35
36pub use alphabet::Alphabet;
37
38#[cfg(not(feature = "std"))]
39use alloc::{string::String, vec::Vec};
40
41#[cfg(not(feature = "std"))]
42use core as std;
43
44use std::fmt;
45
46#[derive(Debug)]
47pub struct DecodeError;
48
49impl fmt::Display for DecodeError {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        write!(f, "Failed to decode the given data")
52    }
53}
54
55#[cfg(feature = "std")]
56impl std::error::Error for DecodeError {
57    fn description(&self) -> &str {
58        "Can not decode the provided data"
59    }
60}
61
62/// Encode an input vector using the given alphabet.
63pub fn encode<A: Alphabet>(alphabet: A, input: &[u8]) -> String {
64    alphabet.encode(input)
65}
66
67/// Decode an input vector using the given alphabet.
68pub fn decode<A: Alphabet>(alphabet: A, input: &str) -> Result<Vec<u8>, DecodeError> {
69    alphabet.decode(input)
70}
71
72#[cfg(test)]
73mod test {
74    use super::decode;
75    use super::encode;
76    extern crate json;
77    use self::json::parse;
78    use std::fs::File;
79    use std::io::Read;
80
81    #[test]
82    fn works() {
83        let mut file = File::open("./fixtures/fixtures.json").unwrap();
84        let mut data = String::new();
85        file.read_to_string(&mut data).unwrap();
86
87        let json = parse(&data).unwrap();
88        let alphabets = &json["alphabets"];
89
90        for value in json["valid"].members() {
91            let alphabet_name = value["alphabet"].as_str().unwrap();
92            let input = value["string"].as_str().unwrap();
93            let alphabet = alphabets[alphabet_name].as_str().unwrap();
94
95            // Alphabet works as unicode
96            let decoded = decode(alphabet, input).unwrap();
97            let encoded = encode(alphabet, &decoded);
98            assert_eq!(encoded, input);
99
100            // Alphabet works as ASCII
101            let decoded = decode(alphabet.as_bytes(), input).unwrap();
102            let encoded = encode(alphabet.as_bytes(), &decoded);
103            assert_eq!(encoded, input);
104        }
105    }
106
107    #[test]
108    fn is_unicode_sound() {
109        // binary, kinda...
110        let alphabet = "😐😀";
111
112        let encoded = encode(alphabet, &[0xff, 0x00, 0xff, 0x00]);
113        let decoded = decode(alphabet, &encoded).unwrap();
114
115        assert_eq!(
116            encoded,
117            "😀😀😀😀😀😀😀😀😐😐😐😐😐😐😐😐😀😀😀😀😀😀😀😀😐😐😐😐😐😐😐😐"
118        );
119        assert_eq!(decoded, &[0xff, 0x00, 0xff, 0x00]);
120    }
121}