in datafusion/functions/src/unicode/lpad.rs [197:279]
fn lpad_impl<'a, V, V2, T>(
string_array: V,
length_array: &Int64Array,
fill_array: Option<V2>,
) -> Result<ArrayRef>
where
V: StringArrayType<'a>,
V2: StringArrayType<'a>,
T: OffsetSizeTrait,
{
let array = if fill_array.is_none() {
let mut builder: GenericStringBuilder<T> = GenericStringBuilder::new();
for (string, length) in string_array.iter().zip(length_array.iter()) {
if let (Some(string), Some(length)) = (string, length) {
if length > i32::MAX as i64 {
return exec_err!("lpad requested length {length} too large");
}
let length = if length < 0 { 0 } else { length as usize };
if length == 0 {
builder.append_value("");
continue;
}
let graphemes = string.graphemes(true).collect::<Vec<&str>>();
if length < graphemes.len() {
builder.append_value(graphemes[..length].concat());
} else {
builder.write_str(" ".repeat(length - graphemes.len()).as_str())?;
builder.write_str(string)?;
builder.append_value("");
}
} else {
builder.append_null();
}
}
builder.finish()
} else {
let mut builder: GenericStringBuilder<T> = GenericStringBuilder::new();
for ((string, length), fill) in string_array
.iter()
.zip(length_array.iter())
.zip(fill_array.unwrap().iter())
{
if let (Some(string), Some(length), Some(fill)) = (string, length, fill) {
if length > i32::MAX as i64 {
return exec_err!("lpad requested length {length} too large");
}
let length = if length < 0 { 0 } else { length as usize };
if length == 0 {
builder.append_value("");
continue;
}
let graphemes = string.graphemes(true).collect::<Vec<&str>>();
let fill_chars = fill.chars().collect::<Vec<char>>();
if length < graphemes.len() {
builder.append_value(graphemes[..length].concat());
} else if fill_chars.is_empty() {
builder.append_value(string);
} else {
for l in 0..length - graphemes.len() {
let c = *fill_chars.get(l % fill_chars.len()).unwrap();
builder.write_char(c)?;
}
builder.write_str(string)?;
builder.append_value("");
}
} else {
builder.append_null();
}
}
builder.finish()
};
Ok(Arc::new(array) as ArrayRef)
}