Skip to main content

simd_kernels/kernels/arithmetic/
string_ops.rs

1// Copyright 2025 Peter Garfield Bower
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Basic string operations for arithmetic module
16
17use crate::enums::error::KernelError;
18use crate::traits::type_unions::Integer;
19use crate::{MaskedArray, StringArray, Vec64};
20use num_traits::NumCast;
21
22/// Generic string concatenation for both String32 and String64 arrays
23pub fn apply_str_str<T: Integer>(
24    lhs: &std::sync::Arc<StringArray<T>>,
25    rhs: &std::sync::Arc<StringArray<T>>,
26) -> Result<StringArray<T>, KernelError> {
27    if lhs.len() != rhs.len() {
28        return Err(KernelError::LengthMismatch(format!(
29            "String concatenation length mismatch: {} vs {}",
30            lhs.len(),
31            rhs.len()
32        )));
33    }
34
35    let mut result_data = Vec64::new();
36    let mut result_offsets = Vec64::with_capacity(lhs.len() + 1);
37    result_offsets.push(NumCast::from(0).unwrap());
38
39    let mut current_offset = NumCast::from(0).unwrap();
40
41    for i in 0..lhs.len() {
42        // Get strings from both arrays
43        let left_str = lhs.get_str(i).unwrap_or("");
44        let right_str = rhs.get_str(i).unwrap_or("");
45
46        // Concatenate
47        let concatenated = format!("{}{}", left_str, right_str);
48        let bytes = concatenated.as_bytes();
49
50        // Add to result data
51        result_data.extend_from_slice(bytes);
52        current_offset = current_offset + NumCast::from(bytes.len()).unwrap();
53        result_offsets.push(current_offset);
54    }
55
56    Ok(StringArray {
57        data: result_data.into(),
58        offsets: result_offsets.into(),
59        null_mask: None, // TODO: Handle null masks properly
60    })
61}