1#![no_std]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6use core::{
7 error::Error,
8 fmt::{self, Debug, Display},
9 iter, str
10};
11
12#[macro_use]
13mod macros;
14
15pub mod alphabet;
16pub mod base32;
17pub mod base64;
18pub mod base85;
19pub mod generic;
20pub mod hex;
21pub mod padding;
22
23mod chunked;
24
25use self::alphabet::{DynAlphabet, DynDecodingTable};
26pub use self::{
27 base32::{
28 Base32HexLower, Base32HexLowerUnpadded, Base32HexUpper, Base32HexUpperUnpadded,
29 Base32Lower, Base32LowerUnpadded, Base32Upper, Base32UpperUnpadded
30 },
31 base64::{Base64, Base64Unpadded, Base64UrlPadded, Base64UrlUnpadded},
32 base85::Z85,
33 hex::{HexLower, HexUpper}
34};
35
36pub trait Encoder: Decoder {
37 fn alphabet(&self) -> &DynAlphabet;
38 fn encoded_len(&self, len: usize) -> Option<usize>;
39
40 fn encode_into_exact<'a>(
41 &self,
42 src: &[u8],
43 dst: &'a mut [u8]
44 ) -> Result<&'a str, EncodeIntoExactError>;
45
46 #[inline]
47 fn encode_into<'a>(&self, src: &[u8], dst: &'a mut [u8]) -> Result<&'a str, EncodeIntoError> {
48 let dst = dst
49 .get_mut(..self.encoded_len(src.len()).ok_or(EncodeIntoError::LengthOverflow)?)
50 .ok_or(EncodeIntoError::TooSmall)?;
51
52 Ok(self.encode_into_exact(src, dst).unwrap())
53 }
54
55 #[cfg(feature = "alloc")]
56 #[inline]
57 fn encode_string(&self, src: &[u8]) -> Option<alloc::string::String> {
58 let mut vec = alloc::vec::Vec::new();
59 let _ = self.encode_into_vec(src, &mut vec)?;
60 Some(unsafe { alloc::string::String::from_utf8_unchecked(vec) })
61 }
62
63 #[cfg(feature = "alloc")]
64 #[inline]
65 fn encode_into_vec<'a>(&self, src: &[u8], dst: &'a mut alloc::vec::Vec<u8>) -> Option<&'a str> {
66 let start = dst.len();
67 dst.extend(iter::repeat_n(0, self.encoded_len(src.len())?));
68 Some(self.encode_into_exact(src, &mut dst[start..]).unwrap())
69 }
70
71 #[cfg(feature = "alloc")]
72 #[inline]
73 fn encode_into_string<'a>(
74 &self,
75 src: &[u8],
76 dst: &'a mut alloc::string::String
77 ) -> Option<&'a str> {
78 self.encode_into_vec(src, unsafe { dst.as_mut_vec() })
79 }
80}
81
82pub trait Decoder {
83 fn decoding_table(&self) -> &DynDecodingTable;
84 fn decoded_len(&self, src: &[u8]) -> Option<usize>;
85
86 fn decode_into_exact<'a>(
87 &self,
88 src: &[u8],
89 dst: &'a mut [u8]
90 ) -> Result<&'a [u8], DecodeIntoExactError>;
91
92 #[inline]
93 fn decode_into<'a>(&self, src: &[u8], dst: &'a mut [u8]) -> Result<&'a [u8], DecodeIntoError> {
94 let dst = dst
95 .get_mut(..self.decoded_len(src).ok_or(DecodeIntoError::InvalidLength)?)
96 .ok_or(DecodeIntoError::TooSmall)?;
97
98 match self.decode_into_exact(src, dst) {
99 Ok(s) => Ok(s),
100 Err(DecodeIntoExactError::InvalidCharacter(i)) => {
101 Err(DecodeIntoError::InvalidCharacter(i))
102 }
103 Err(DecodeIntoExactError::InvalidChunk { index, len }) => {
104 Err(DecodeIntoError::InvalidChunk { index, len })
105 }
106 Err(DecodeIntoExactError::NonCanonical) => Err(DecodeIntoError::NonCanonical),
107 Err(DecodeIntoExactError::InvalidLength | DecodeIntoExactError::LengthMismatch) => {
108 unreachable!()
109 }
110 }
111 }
112
113 #[cfg(feature = "alloc")]
114 #[inline]
115 fn decode_vec(&self, src: &[u8]) -> Result<alloc::vec::Vec<u8>, DecodeVecError> {
116 let mut vec = alloc::vec::Vec::new();
117 let _ = self.decode_into_vec(src, &mut vec)?;
118 Ok(vec)
119 }
120
121 #[cfg(feature = "alloc")]
122 #[inline]
123 fn decode_into_vec<'a>(
124 &self,
125 src: &[u8],
126 dst: &'a mut alloc::vec::Vec<u8>
127 ) -> Result<&'a [u8], DecodeVecError> {
128 let start = dst.len();
129 dst.extend(iter::repeat_n(0, self.decoded_len(src).ok_or(DecodeVecError::InvalidLength)?));
130
131 match self.decode_into_exact(src, &mut dst[start..]) {
132 Ok(dst) => Ok(dst),
133 Err(DecodeIntoExactError::InvalidCharacter(i)) => {
134 Err(DecodeVecError::InvalidCharacter(i))
135 }
136 Err(DecodeIntoExactError::InvalidChunk { index, len }) => {
137 Err(DecodeVecError::InvalidChunk { index, len })
138 }
139 Err(DecodeIntoExactError::NonCanonical) => Err(DecodeVecError::NonCanonical),
140 Err(DecodeIntoExactError::InvalidLength | DecodeIntoExactError::LengthMismatch) => {
141 unreachable!()
142 }
143 }
144 }
145}
146
147#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
148pub enum EncodeIntoError {
149 LengthOverflow,
150 TooSmall
151}
152
153#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
154pub enum EncodeIntoExactError {
155 LengthOverflow,
156 LengthMismatch
157}
158
159#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
160pub enum DecodeIntoError {
161 InvalidLength,
162 TooSmall,
163 InvalidCharacter(usize),
164 NonCanonical,
165 InvalidChunk { index: usize, len: usize }
166}
167
168#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
169pub enum DecodeIntoExactError {
170 InvalidLength,
171 LengthMismatch,
172 InvalidCharacter(usize),
173 NonCanonical,
174 InvalidChunk { index: usize, len: usize }
175}
176
177#[cfg(feature = "alloc")]
178#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
179pub enum DecodeVecError {
180 InvalidLength,
181 InvalidCharacter(usize),
182 NonCanonical,
183 InvalidChunk { index: usize, len: usize }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[allow(dead_code)]
191 fn assert_dyn_safe(_: &dyn Encoder) {}
192}