You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: concat_agg.rs
    path of file: ./repos/Daft/src/daft-core/src/array/ops
    
    the code of the file until where you have to start completion: use crate::array::{
    growable::{make_growable, Growable},
    ListArray,
};
use arrow2::{bitmap::utils::SlicesIterator, offset::OffsetsBuffer, types::Index};
use common_error::DaftResult;

use super::{as_arrow::AsArrow, DaftConcatAggable};

#[cfg(feature = "python")]
impl DaftConcatAggable for crate::datatypes::PythonArray {
    type Output = DaftResult<Self>;
    fn concat(&self) -> Self::Output {
        use crate::array::pseudo_arrow::PseudoArrowArray;
        use pyo3::prelude::*;
        use pyo3::types::PyList;

        let pyobj_vec = self.as_arrow().to_pyobj_vec();

        let pylist: Py<PyList> = Python::with_gil(|py| -> PyResult<Py<PyList>> {
            let pylist: Py<PyList> = PyList::empty(py).into();
            for pyobj in pyobj_vec {
                if !pyobj.is_none(py) {
                    pylist.call_method1(py, pyo3::intern!(py, "extend"), (pyobj,))?;
                }
            }
            Ok(pylist)
        })?;
        let arrow_array = PseudoArrowArray::<PyObject>::from_pyobj_vec(vec![pylist.into()]);
        Self::new(self.field().clone().into(), Box::new(arrow_array))
    }
    fn grouped_concat(&self, groups: &super::GroupIndices) -> Self::Output {
        use crate::array::pseudo_arrow::PseudoArrowArray;
        use pyo3::prelude::*;
        use pyo3::types::PyList;

        let mut result_pylists: Vec<PyObject> = Vec::with_capacity(groups.len());

        Python::with_gil(|py| -> DaftResult<()> {
            for group in groups {
       
    
    fn concat(&self) -> Self::Output {
        if self.null_count() == 0 {
            let new_offsets = OffsetsBuffer::<i64>::try_from(vec![0, *self.offsets().last()])?;
            return Ok(ListArray::new(
                self.field.clone(),
                self.flat_child.clone(),
                new_offsets,
                None,
            ));
        }

        // Only the all-null case leads to a null result. If any single element is non-null (e.g. an empty list []),
        // The concat will successfully return a single non-null element.
        let new_validity = match self.validity() {
            Some(validity) if validity.unset_bits() == self.len() => {
                Some(arrow2::bitmap::Bitmap::from(vec![false]))
            }
            _ => None,
        };

        // Re-grow the child, dropping elements where the parent is null
        let mut child_growable: Box<dyn Growable> = make_growable(
            self.flat_child.name(),
            self.flat_child.data_type(),
            vec![&self.flat_child],
            true,
            self.flat_child.len(), // Conservatively reserve a capacity == full size of the child
        );
        for (start_valid, len_valid) in SlicesIterator::new(self.validity().unwrap()) {
            let child_start = self.offsets().start_end(start_valid).0;
            let child_end = self.offsets().start_end(start_valid + len_valid - 1).1;
            child_growable.extend(0, child_start, child_end - child_start);
        }
        let new_child = child_growable.build()?;
        let new_offsets = OffsetsBuffer::<i64>::try_from(vec![0, new_child.len() as i64])?;

        Ok(ListArray::new(
            self.field.clone(),
            new_child,
            new_offsets,
            new_validity,
        ))
    }