antelope/chain/
blob.rs

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        // Remove padding characters '=' from the end of the string
31        let value_without_padding: String = value.trim_end_matches('=').to_string();
32
33        // Convert base64 string to bytes
34        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}