forked from opendevtools/base45
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencode.rs
More file actions
89 lines (80 loc) · 2.37 KB
/
Copy pathencode.rs
File metadata and controls
89 lines (80 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::alphabet::{self, SIZE, SIZE_SIZE};
#[inline(always)]
fn divmod<const N: u32>(x: u32) -> (u32, u32) {
(x / N, x % N)
}
#[inline(always)]
fn ae(b: u8) -> u8 {
match alphabet::encode(b) {
Some(ch) => ch,
#[cfg(feature = "unsafe")]
// SAFETY: encode for this is highly unlikely to ever reach this point.
None => unsafe { core::hint::unreachable_unchecked() },
#[cfg(not(feature = "unsafe"))]
None => unreachable!(),
}
}
fn encode_buffer(input: &[u8]) -> String {
// setup
let (input, remainder) = input.as_chunks::<2>();
let mut s = Vec::with_capacity(input.len() + input.len().div_ceil(2));
// Core function
#[inline(always)]
fn core_fn([_first, _second]: [u8; 2], s: &mut Vec<u8>) {
let v = (_first as u32 * 256) + _second as u32;
let (e, rest) = divmod::<SIZE_SIZE>(v);
let (d, c) = divmod::<SIZE>(rest);
s.extend_from_slice(&[ae(c as _), ae(d as _), ae(e as _)]);
}
// take remainder AoT
for c in input {
core_fn(*c, &mut s);
}
// Final byte
if let &[_0] = remainder {
let (d, c) = divmod::<SIZE>(_0 as u32);
s.extend_from_slice(&[ae(c as _), ae(d as _)]);
}
#[cfg(feature = "unsafe")]
// SAFETY: we control all bytes that enter this vector.
unsafe {
String::from_utf8_unchecked(s)
}
#[cfg(not(feature = "unsafe"))]
String::from_utf8(s).expect("All bytes encoded must be ascii")
}
/// Encode a string to base45
///
/// The function takes a string containing only characters in
/// in the range U+0000 to U+00FF.
///
/// ```rust,no_run
/// # fn main() {
/// let encoded = base45::encode("Hello!!");
/// assert_eq!(encoded, "%69 VD92EX0");
/// # }
/// ```
pub fn encode(input: impl AsRef<[u8]>) -> String {
encode_buffer(input.as_ref())
}
/// Encode a buffer to base45
///
/// The function takes an arbitrary buffer and encodes it to base45.
///
/// ## Updates
///
/// As of v3.1.0, this function is exactly eqivalent to encode.
///
/// ```rust,no_run
/// # fn main() {
/// let encoded = base45::encode_from_buffer(vec![72,101,108,108,111,33,33]);
/// assert_eq!(encoded, "%69 VD92EX0");
/// # }
/// ```
#[deprecated(
since = "3.1.0",
note = "Equivalent to `encode`. Use `encode` instead."
)]
pub fn encode_from_buffer(input: impl AsRef<[u8]>) -> String {
encode_buffer(input.as_ref())
}