mcf/
base64.rs

1//! Base64 encoding variants.
2
3#![cfg(feature = "base64")]
4
5use base64ct::{Base64Bcrypt, Base64Crypt, Base64ShaCrypt, Encoding as _, Error as B64Error};
6
7#[cfg(feature = "alloc")]
8use alloc::{string::String, vec::Vec};
9
10/// Base64 encoding variants used in various MCF encodings.
11#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
12#[non_exhaustive]
13pub enum Base64 {
14    /// bcrypt encoding.
15    ///
16    /// ```text
17    /// ./         [A-Z]      [a-z]      [0-9]
18    /// 0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
19    /// ```
20    Bcrypt,
21
22    /// `crypt(3)` encoding.
23    ///
24    /// ```text
25    /// [.-9]      [A-Z]      [a-z]
26    /// 0x2e-0x39, 0x41-0x5a, 0x61-0x7a
27    /// ```
28    Crypt,
29
30    /// `crypt(3)` Base64 encoding for the following schemes:
31    /// - sha1_crypt,
32    /// - sha256_crypt,
33    /// - sha512_crypt,
34    /// - md5_crypt
35    ///
36    /// ```text
37    /// [.-9]      [A-Z]      [a-z]
38    /// 0x2e-0x39, 0x41-0x5a, 0x61-0x7a
39    /// ```
40    ShaCrypt,
41}
42
43impl Base64 {
44    /// Decode a Base64 string into the provided destination buffer.
45    pub fn decode(self, src: impl AsRef<[u8]>, dst: &mut [u8]) -> Result<&[u8], B64Error> {
46        match self {
47            Self::Bcrypt => Base64Bcrypt::decode(src, dst),
48            Self::Crypt => Base64Crypt::decode(src, dst),
49            Self::ShaCrypt => Base64ShaCrypt::decode(src, dst),
50        }
51    }
52
53    /// Decode a Base64 string into a byte vector.
54    #[cfg(feature = "alloc")]
55    pub fn decode_vec(self, input: &str) -> Result<Vec<u8>, B64Error> {
56        match self {
57            Self::Bcrypt => Base64Bcrypt::decode_vec(input),
58            Self::Crypt => Base64Crypt::decode_vec(input),
59            Self::ShaCrypt => Base64ShaCrypt::decode_vec(input),
60        }
61    }
62
63    /// Encode the input byte slice as Base64.
64    ///
65    /// Writes the result into the provided destination slice, returning an
66    /// ASCII-encoded Base64 string value.
67    pub fn encode<'a>(self, src: &[u8], dst: &'a mut [u8]) -> Result<&'a str, B64Error> {
68        match self {
69            Self::Bcrypt => Base64Bcrypt::encode(src, dst),
70            Self::Crypt => Base64Crypt::encode(src, dst),
71            Self::ShaCrypt => Base64ShaCrypt::encode(src, dst),
72        }
73        .map_err(Into::into)
74    }
75
76    /// Encode input byte slice into a [`String`] containing Base64.
77    ///
78    /// # Panics
79    /// If `input` length is greater than `usize::MAX/4`.
80    #[cfg(feature = "alloc")]
81    pub fn encode_string(self, input: &[u8]) -> String {
82        match self {
83            Self::Bcrypt => Base64Bcrypt::encode_string(input),
84            Self::Crypt => Base64Crypt::encode_string(input),
85            Self::ShaCrypt => Base64ShaCrypt::encode_string(input),
86        }
87    }
88
89    /// Get the length of Base64 produced by encoding the given bytes.
90    pub fn encoded_len(self, bytes: &[u8]) -> usize {
91        match self {
92            Self::Bcrypt => Base64Bcrypt::encoded_len(bytes),
93            Self::Crypt => Base64Crypt::encoded_len(bytes),
94            Self::ShaCrypt => Base64ShaCrypt::encoded_len(bytes),
95        }
96    }
97}