1use base64::{
2 alphabet,
3 engine::{general_purpose::PAD, GeneralPurpose},
4 Engine as _,
5};
6
7use crate::util::array_equals;
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum BlobType {
11 Bytes(Vec<u8>),
12 String(String),
13}
14
15pub struct Blob {
16 pub array: Vec<u8>,
17}
18
19pub const STANDARD: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, PAD);
20
21impl Blob {
22 pub fn from(value: BlobType) -> Result<Blob, &'static str> {
23 match value {
24 BlobType::Bytes(bytes) => Ok(Blob { array: bytes }),
25 BlobType::String(string) => Self::from_string(&string),
26 }
27 }
28
29 pub fn from_string(value: &str) -> Result<Blob, &'static str> {
30 let value_without_padding: String = value.trim_end_matches('=').to_string();
32
33 match STANDARD.decode(value_without_padding) {
35 Ok(bytes) => Ok(Blob { array: bytes }),
36 Err(_) => Err("Invalid base64 string"),
37 }
38 }
39
40 pub fn equals(&self, other: &BlobType) -> bool {
41 if let BlobType::Bytes(bytes) = other {
42 array_equals(&self.array, bytes)
43 } else {
44 false
45 }
46 }
47
48 pub fn base64_string(&self) -> String {
49 STANDARD.encode(&self.array)
50 }
51
52 pub fn utf8_string(&self) -> Result<String, &'static str> {
53 match String::from_utf8(self.array.clone()) {
54 Ok(utf8_string) => Ok(utf8_string),
55 Err(_) => Err("Invalid UTF-8 string"),
56 }
57 }
58}