Skip to main content

reifydb_routine/function/blob/
utf8.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use 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 BlobUtf8 {
13	info: RoutineInfo,
14}
15
16impl Default for BlobUtf8 {
17	fn default() -> Self {
18		Self::new()
19	}
20}
21
22impl BlobUtf8 {
23	pub fn new() -> Self {
24		Self {
25			info: RoutineInfo::new("blob::utf8"),
26		}
27	}
28}
29
30impl<'a> Routine<FunctionContext<'a>> for BlobUtf8 {
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 utf8_str = container.get(i).unwrap();
63						let blob = Blob::from_utf8(Fragment::internal(utf8_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 BlobUtf8 {
93	fn kinds(&self) -> &[FunctionKind] {
94		&[FunctionKind::Scalar]
95	}
96}