cyware_convert/encoding/
base64.rs

1use data_encoding;
2#[cfg(target_family = "wasm")]
3use serde::{Deserialize, Serialize};
4
5use crate::Operation;
6use crate::OperationError;
7
8#[derive(Clone, Copy)]
9#[cfg_attr(target_family = "wasm", derive(Serialize, Deserialize))]
10#[cfg_attr(target_family = "wasm", serde(rename_all = "snake_case"))]
11pub enum Base64Format {
12    Standard,
13    Url,
14    Mime,
15}
16
17#[derive(Clone)]
18#[cfg_attr(target_family = "wasm", derive(Serialize, Deserialize))]
19pub struct Base64Decode {
20    format: Base64Format,
21    pad: bool,
22}
23
24impl Operation for Base64Decode {
25    fn execute(&self, input: &[u8]) -> Result<Vec<u8>, OperationError> {
26        match (&self.format, self.pad) {
27            (Base64Format::Standard, false) => data_encoding::BASE64_NOPAD.decode(input),
28            (Base64Format::Standard, true) => data_encoding::BASE64.decode(input),
29            (Base64Format::Url, false) => data_encoding::BASE64URL_NOPAD.decode(input),
30            (Base64Format::Url, true) => data_encoding::BASE64URL.decode(input),
31            (Base64Format::Mime, _) => data_encoding::BASE64_MIME.decode(input),
32        }
33        .map_err(|_| OperationError::DecodeError("Invalid base64 input".to_string()))
34    }
35}
36
37impl Base64Decode {
38    pub const fn new(format: Base64Format, pad: bool) -> Self {
39        Base64Decode { format, pad }
40    }
41}
42
43#[derive(Clone)]
44#[cfg_attr(target_family = "wasm", derive(Serialize, Deserialize))]
45pub struct Base64Encode {
46    format: Base64Format,
47    pad: bool,
48}
49
50impl Operation for Base64Encode {
51    fn execute(&self, input: &[u8]) -> Result<Vec<u8>, OperationError> {
52        let encoded = match (&self.format, self.pad) {
53            (Base64Format::Standard, false) => data_encoding::BASE64_NOPAD.encode(input),
54            (Base64Format::Standard, true) => data_encoding::BASE64.encode(input),
55            (Base64Format::Url, false) => data_encoding::BASE64URL_NOPAD.encode(input),
56            (Base64Format::Url, true) => data_encoding::BASE64URL.encode(input),
57            (Base64Format::Mime, _) => data_encoding::BASE64_MIME.encode(input),
58        };
59        Ok(encoded.into())
60    }
61}
62
63impl Base64Encode {
64    pub const fn new(format: Base64Format, pad: bool) -> Self {
65        Base64Encode { format, pad }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn base64_decode() {
75        let encoder = Base64Decode::new(Base64Format::Standard, true);
76        let actual = encoder.execute("Y2FpZG8=".as_bytes()).unwrap();
77        let expected = "caido".as_bytes().to_vec();
78        assert_eq!(actual, expected);
79    }
80
81    #[test]
82    fn base64_encode() {
83        let encoder = Base64Encode::new(Base64Format::Standard, true);
84        let actual = encoder.execute("caido".as_bytes()).unwrap();
85        let expected = "Y2FpZG8=".as_bytes().to_vec();
86        assert_eq!(actual, expected);
87    }
88}