reifydb_function/blob/
b64url.rs1use reifydb_core::value::column::data::ColumnData;
5use reifydb_type::{
6 fragment::Fragment,
7 value::{blob::Blob, r#type::Type},
8};
9
10use crate::{
11 ScalarFunction, ScalarFunctionContext,
12 error::{ScalarFunctionError, ScalarFunctionResult},
13 propagate_options,
14};
15
16pub struct BlobB64url;
17
18impl BlobB64url {
19 pub fn new() -> Self {
20 Self
21 }
22}
23
24impl ScalarFunction for BlobB64url {
25 fn scalar(&self, ctx: ScalarFunctionContext) -> ScalarFunctionResult<ColumnData> {
26 if let Some(result) = propagate_options(self, &ctx) {
27 return result;
28 }
29
30 let columns = ctx.columns;
31 let row_count = ctx.row_count;
32
33 if columns.len() != 1 {
35 return Err(ScalarFunctionError::ArityMismatch {
36 function: ctx.fragment.clone(),
37 expected: 1,
38 actual: columns.len(),
39 });
40 }
41
42 let column = columns.get(0).unwrap();
43
44 match &column.data() {
45 ColumnData::Utf8 {
46 container,
47 ..
48 } => {
49 let mut result_data = Vec::with_capacity(container.data().len());
50 let mut result_bitvec = Vec::with_capacity(row_count);
51
52 for i in 0..row_count {
53 if container.is_defined(i) {
54 let b64url_str = &container[i];
55 let blob = Blob::from_b64url(Fragment::internal(b64url_str))?;
56 result_data.push(blob);
57 result_bitvec.push(true);
58 } else {
59 result_data.push(Blob::empty());
60 result_bitvec.push(false);
61 }
62 }
63
64 Ok(ColumnData::blob_with_bitvec(result_data, result_bitvec))
65 }
66 other => Err(ScalarFunctionError::InvalidArgumentType {
67 function: ctx.fragment.clone(),
68 argument_index: 0,
69 expected: vec![Type::Utf8],
70 actual: other.get_type(),
71 }),
72 }
73 }
74
75 fn return_type(&self, _input_types: &[Type]) -> Type {
76 Type::Blob
77 }
78}