fn lpad_impl()

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)
}