Fast path for `Utf8` or `LargeUtf8` arrays that are ASCII-only. We can use a single pass over the buffer and operate directly on bytes.
(
string_array: &GenericStringArray<T>,
)
| 189 | /// Fast path for `Utf8` or `LargeUtf8` arrays that are ASCII-only. We can use a |
| 190 | /// single pass over the buffer and operate directly on bytes. |
| 191 | fn initcap_ascii_array<T: OffsetSizeTrait>( |
| 192 | string_array: &GenericStringArray<T>, |
| 193 | ) -> ArrayRef { |
| 194 | let offsets = string_array.offsets(); |
| 195 | let src = string_array.value_data(); |
| 196 | let first_offset = offsets.first().unwrap().as_usize(); |
| 197 | let last_offset = offsets.last().unwrap().as_usize(); |
| 198 | |
| 199 | // For sliced arrays, only convert the visible bytes, not the entire input |
| 200 | // buffer. |
| 201 | let mut out = Vec::with_capacity(last_offset - first_offset); |
| 202 | |
| 203 | for window in offsets.windows(2) { |
| 204 | let start = window[0].as_usize(); |
| 205 | let end = window[1].as_usize(); |
| 206 | |
| 207 | let mut prev_is_alnum = false; |
| 208 | for &b in &src[start..end] { |
| 209 | let converted = if prev_is_alnum { |
| 210 | b.to_ascii_lowercase() |
| 211 | } else { |
| 212 | b.to_ascii_uppercase() |
| 213 | }; |
| 214 | out.push(converted); |
| 215 | prev_is_alnum = b.is_ascii_alphanumeric(); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | let values = Buffer::from_vec(out); |
| 220 | let out_offsets = if first_offset == 0 { |
| 221 | offsets.clone() |
| 222 | } else { |
| 223 | // For sliced arrays, we need to rebase the offsets to reflect that the |
| 224 | // output only contains the bytes in the visible slice. |
| 225 | let rebased_offsets = offsets |
| 226 | .iter() |
| 227 | .map(|offset| T::usize_as(offset.as_usize() - first_offset)) |
| 228 | .collect::<Vec<_>>(); |
| 229 | OffsetBuffer::<T>::new(rebased_offsets.into()) |
| 230 | }; |
| 231 | |
| 232 | // SAFETY: ASCII case conversion preserves byte length, so the original |
| 233 | // string boundaries are preserved. `out_offsets` is either identical to |
| 234 | // the input offsets or a rebased version relative to the compacted values |
| 235 | // buffer. |
| 236 | Arc::new(unsafe { |
| 237 | GenericStringArray::<T>::new_unchecked( |
| 238 | out_offsets, |
| 239 | values, |
| 240 | string_array.nulls().cloned(), |
| 241 | ) |
| 242 | }) |
| 243 | } |
| 244 | |
| 245 | fn initcap_utf8view(args: &[ArrayRef]) -> Result<ArrayRef> { |
| 246 | let string_view_array = as_string_view_array(&args[0])?; |
no test coverage detected
searching dependent graphs…