akar_function/scalar/
blob.rs1use super::get_string;
2use crate::registry::*;
3use akar_common::types::Value;
4
5use base64::prelude::*;
8
9fn encode_base64(data: &[u8]) -> String {
10 BASE64_STANDARD.encode(data)
11}
12
13fn decode_base64(s: &str) -> Result<Vec<u8>, String> {
14 BASE64_STANDARD.decode(s).map_err(|e| format!("Invalid base64: {}", e))
15}
16
17pub(crate) fn evaluate_blob(op: BlobOp, args: &[Value]) -> Result<Value, String> {
19 match op {
20 BlobOp::Encode => {
21 let s = get_string(&args[0])?;
22 Ok(Value::Blob(s.into_bytes()))
23 }
24 BlobOp::Decode => {
25 let bytes = match &args[0] {
26 Value::Blob(b) => b.clone(),
27 _ => return Err("DECODE requires a blob argument".into()),
28 };
29 let s = String::from_utf8(bytes).map_err(|_| {
30 "Failure in decode: could not convert blob to UTF8 string, the blob contained invalid UTF8 characters".to_string()
31 })?;
32 Ok(Value::String(s))
33 }
34 BlobOp::OctetLength => {
35 let len = match &args[0] {
36 Value::Blob(b) => b.len() as i64,
37 _ => return Err("OCTET_LENGTH requires a blob argument".into()),
38 };
39 Ok(Value::Int64(len))
40 }
41 BlobOp::BlobFromBytes => match &args[0] {
42 Value::Blob(b) => Ok(Value::Blob(b.clone())),
43 Value::String(s) => Ok(Value::Blob(s.clone().into_bytes())),
44 _ => Err("blob_from_bytes requires string or blob".into()),
45 },
46 BlobOp::ToBase64 => {
47 let bytes = match &args[0] {
48 Value::Blob(b) => b,
49 _ => return Err("to_base64 requires a blob argument".into()),
50 };
51 Ok(Value::String(encode_base64(bytes)))
52 }
53 BlobOp::FromBase64 => {
54 let s = match &args[0] {
55 Value::String(s) => s,
56 _ => return Err("from_base64 requires a string argument".into()),
57 };
58 let decoded = decode_base64(s)?;
59 Ok(Value::Blob(decoded))
60 }
61 }
62}