(
string_array: V,
target_len: usize,
fill: &str,
)
| 243 | } |
| 244 | |
| 245 | fn lpad_scalar_unicode<'a, V: StringArrayType<'a> + Copy, T: OffsetSizeTrait>( |
| 246 | string_array: V, |
| 247 | target_len: usize, |
| 248 | fill: &str, |
| 249 | ) -> Result<ArrayRef> { |
| 250 | let fill_chars: Vec<char> = fill.chars().collect(); |
| 251 | |
| 252 | // With a scalar `target_len` and `fill`, we can precompute a padding buffer |
| 253 | // of `target_len` fill characters repeated cyclically. Because Unicode |
| 254 | // characters are variable-width, we build a byte-offset table to map from |
| 255 | // character count to the corresponding byte position in the padding buffer. |
| 256 | let (padding_buf, char_byte_offsets) = if !fill_chars.is_empty() { |
| 257 | let mut buf = String::new(); |
| 258 | let mut offsets = Vec::with_capacity(target_len + 1); |
| 259 | offsets.push(0usize); |
| 260 | for i in 0..target_len { |
| 261 | buf.push(fill_chars[i % fill_chars.len()]); |
| 262 | offsets.push(buf.len()); |
| 263 | } |
| 264 | (buf, offsets) |
| 265 | } else { |
| 266 | (String::new(), vec![0]) |
| 267 | }; |
| 268 | |
| 269 | // Each output row is `target_len` chars; multiply by 4 (max UTF-8 bytes |
| 270 | // per char) for an upper bound in bytes. |
| 271 | let data_capacity = string_array.len().saturating_mul(target_len * 4); |
| 272 | let mut builder = |
| 273 | GenericStringBuilder::<T>::with_capacity(string_array.len(), data_capacity); |
| 274 | |
| 275 | for maybe_string in string_array.iter() { |
| 276 | match maybe_string { |
| 277 | Some(string) => match char_count_or_boundary(string, target_len) { |
| 278 | StringCharLen::ByteOffset(offset) => { |
| 279 | builder.append_value(&string[..offset]); |
| 280 | } |
| 281 | StringCharLen::CharCount(char_count) => { |
| 282 | if !fill_chars.is_empty() { |
| 283 | let pad_chars = target_len - char_count; |
| 284 | let pad_bytes = char_byte_offsets[pad_chars]; |
| 285 | builder.write_str(&padding_buf[..pad_bytes])?; |
| 286 | } |
| 287 | builder.append_value(string); |
| 288 | } |
| 289 | }, |
| 290 | None => builder.append_null(), |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | Ok(Arc::new(builder.finish()) as ArrayRef) |
| 295 | } |
| 296 | |
| 297 | /// Left-pads `string` to `target_len` using the fill string (default: space). |
| 298 | /// Truncates from the right if `string` is already longer than `target_len`. |
nothing calls this directly
no test coverage detected
searching dependent graphs…