reifydb_routine/function/blob/
b64.rs1use reifydb_core::value::column::{ColumnWithName, buffer::ColumnBuffer, columns::Columns};
5use reifydb_type::{
6 fragment::Fragment,
7 value::{blob::Blob, r#type::Type},
8};
9
10use crate::routine::{Function, FunctionKind, Routine, RoutineInfo, context::FunctionContext, error::RoutineError};
11
12pub struct BlobB64 {
13 info: RoutineInfo,
14}
15
16impl Default for BlobB64 {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl BlobB64 {
23 pub fn new() -> Self {
24 Self {
25 info: RoutineInfo::new("blob::b64"),
26 }
27 }
28}
29
30impl<'a> Routine<FunctionContext<'a>> for BlobB64 {
31 fn info(&self) -> &RoutineInfo {
32 &self.info
33 }
34
35 fn return_type(&self, _input_types: &[Type]) -> Type {
36 Type::Blob
37 }
38
39 fn execute(&self, ctx: &mut FunctionContext<'a>, args: &Columns) -> Result<Columns, RoutineError> {
40 if args.len() != 1 {
41 return Err(RoutineError::FunctionArityMismatch {
42 function: ctx.fragment.clone(),
43 expected: 1,
44 actual: args.len(),
45 });
46 }
47
48 let column = &args[0];
49 let (data, bitvec) = column.unwrap_option();
50 let row_count = data.len();
51
52 match data {
53 ColumnBuffer::Utf8 {
54 container,
55 ..
56 } => {
57 let mut result_data = Vec::with_capacity(container.len());
58 let mut result_bitvec = Vec::with_capacity(row_count);
59
60 for i in 0..row_count {
61 if container.is_defined(i) {
62 let b64_str = container.get(i).unwrap();
63 let blob = Blob::from_b64(Fragment::internal(b64_str))?;
64 result_data.push(blob);
65 result_bitvec.push(true);
66 } else {
67 result_data.push(Blob::empty());
68 result_bitvec.push(false);
69 }
70 }
71
72 let result_col_data = ColumnBuffer::blob_with_bitvec(result_data, result_bitvec);
73 let final_data = match bitvec {
74 Some(bv) => ColumnBuffer::Option {
75 inner: Box::new(result_col_data),
76 bitvec: bv.clone(),
77 },
78 None => result_col_data,
79 };
80 Ok(Columns::new(vec![ColumnWithName::new(ctx.fragment.clone(), final_data)]))
81 }
82 other => Err(RoutineError::FunctionInvalidArgumentType {
83 function: ctx.fragment.clone(),
84 argument_index: 0,
85 expected: vec![Type::Utf8],
86 actual: other.get_type(),
87 }),
88 }
89 }
90}
91
92impl Function for BlobB64 {
93 fn kinds(&self) -> &[FunctionKind] {
94 &[FunctionKind::Scalar]
95 }
96}