use crate::compute::concat;
use num_traits::{abs, clamp};
use crate::{
array::{new_null_array, Array},
error::{ArrowError, Result},
};
pub fn shift(array: &dyn Array, offset: i64) -> Result<Box<dyn Array>> {
if abs(offset) as usize > array.len() {
return Err(ArrowError::InvalidArgumentError(format!(
"Shift's absolute offset must be smaller or equal to the arrays length. Offset is {}, length is {}",
abs(offset), array.len()
)));
}
let slice_offset = clamp(-offset, 0, array.len() as i64) as usize;
let length = array.len() - abs(offset) as usize;
let slice = array.slice(slice_offset, length);
let nulls = abs(offset as i64) as usize;
let null_array = new_null_array(array.data_type().clone(), nulls);
if offset > 0 {
concat::concatenate(&[null_array.as_ref(), slice.as_ref()])
} else {
concat::concatenate(&[slice.as_ref(), null_array.as_ref()])
}
}