base64ct/alphabet/
shacrypt.rs
1use super::{Alphabet, DecodeStep, EncodeStep};
4
5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
16pub struct Base64ShaCrypt;
17
18impl Alphabet for Base64ShaCrypt {
19 const BASE: u8 = b'.';
20
21 const DECODER: &'static [DecodeStep] = &[
22 DecodeStep::Range(b'.'..=b'9', -45),
23 DecodeStep::Range(b'A'..=b'Z', -52),
24 DecodeStep::Range(b'a'..=b'z', -58),
25 ];
26
27 const ENCODER: &'static [EncodeStep] =
28 &[EncodeStep::Apply(b'9', 7), EncodeStep::Apply(b'Z', 6)];
29
30 const PADDED: bool = false;
31
32 type Unpadded = Self;
33
34 #[inline(always)]
35 fn decode_3bytes(src: &[u8], dst: &mut [u8]) -> i16 {
36 debug_assert_eq!(src.len(), 4);
37 debug_assert!(dst.len() >= 3, "dst too short: {}", dst.len());
38
39 let c0 = Self::decode_6bits(src[0]);
40 let c1 = Self::decode_6bits(src[1]);
41 let c2 = Self::decode_6bits(src[2]);
42 let c3 = Self::decode_6bits(src[3]);
43
44 dst[0] = (c0 | ((c1 & 0x3) << 6)) as u8;
45 dst[1] = ((c1 >> 2) | ((c2 & 0xF) << 4)) as u8;
46 dst[2] = ((c2 >> 4) | (c3 << 2)) as u8;
47
48 ((c0 | c1 | c2 | c3) >> 8) & 1
49 }
50
51 #[inline(always)]
52 fn encode_3bytes(src: &[u8], dst: &mut [u8]) {
53 debug_assert_eq!(src.len(), 3);
54 debug_assert!(dst.len() >= 4, "dst too short: {}", dst.len());
55
56 let b0 = src[0] as i16;
57 let b1 = src[1] as i16;
58 let b2 = src[2] as i16;
59
60 dst[0] = Self::encode_6bits(b0 & 63);
61 dst[1] = Self::encode_6bits(((b1 << 2) | (b0 >> 6)) & 63);
62 dst[2] = Self::encode_6bits(((b2 << 4) | (b1 >> 4)) & 63);
63 dst[3] = Self::encode_6bits(b2 >> 2);
64 }
65}