use std::hash::Hash;
use std::sync::Arc;
use crate::array::indexable::{AsIndexed, Indexable};
use crate::{
array::{primitive::MutablePrimitiveArray, Array, MutableArray, TryExtend, TryPush},
bitmap::MutableBitmap,
datatypes::DataType,
error::Result,
};
use super::value_map::ValueMap;
use super::{DictionaryArray, DictionaryKey};
#[derive(Debug)]
pub struct MutableDictionaryArray<K: DictionaryKey, M: MutableArray> {
data_type: DataType,
map: ValueMap<K, M>,
keys: MutablePrimitiveArray<K>,
}
impl<K: DictionaryKey, M: MutableArray> From<MutableDictionaryArray<K, M>> for DictionaryArray<K> {
fn from(other: MutableDictionaryArray<K, M>) -> Self {
unsafe {
DictionaryArray::<K>::try_new_unchecked(
other.data_type,
other.keys.into(),
other.map.into_values().as_box(),
)
.unwrap()
}
}
}
impl<K: DictionaryKey, M: MutableArray + Default> MutableDictionaryArray<K, M> {
pub fn new() -> Self {
Self::try_empty(M::default()).unwrap()
}
}
impl<K: DictionaryKey, M: MutableArray + Default> Default for MutableDictionaryArray<K, M> {
fn default() -> Self {
Self::new()
}
}
impl<K: DictionaryKey, M: MutableArray> MutableDictionaryArray<K, M> {
pub fn try_empty(values: M) -> Result<Self> {
Ok(Self::from_value_map(ValueMap::<K, M>::try_empty(values)?))
}
pub fn from_values(values: M) -> Result<Self>
where
M: Indexable,
M::Type: Eq + Hash,
{
Ok(Self::from_value_map(ValueMap::<K, M>::from_values(values)?))
}
fn from_value_map(value_map: ValueMap<K, M>) -> Self {
let keys = MutablePrimitiveArray::<K>::new();
let data_type =
DataType::Dictionary(K::KEY_TYPE, Arc::new(value_map.data_type().clone()), false);
Self {
data_type,
map: value_map,
keys,
}
}
pub fn into_empty(self) -> Self {
Self::from_value_map(self.map)
}
pub fn to_empty(&self) -> Self
where
M: Clone,
{
Self::from_value_map(self.map.clone())
}
pub fn push_null(&mut self) {
self.keys.push(None)
}
pub fn values(&self) -> &M {
self.map.values()
}
pub fn into_arc(self) -> Arc<dyn Array> {
let a: DictionaryArray<K> = self.into();
Arc::new(a)
}
pub fn into_box(self) -> Box<dyn Array> {
let a: DictionaryArray<K> = self.into();
Box::new(a)
}
pub fn reserve(&mut self, additional: usize) {
self.keys.reserve(additional);
}
pub fn shrink_to_fit(&mut self) {
self.map.shrink_to_fit();
self.keys.shrink_to_fit();
}
pub fn keys(&self) -> &MutablePrimitiveArray<K> {
&self.keys
}
fn take_into(&mut self) -> DictionaryArray<K> {
DictionaryArray::<K>::try_new(
self.data_type.clone(),
std::mem::take(&mut self.keys).into(),
self.map.take_into(),
)
.unwrap()
}
}
impl<K: DictionaryKey, M: 'static + MutableArray> MutableArray for MutableDictionaryArray<K, M> {
fn len(&self) -> usize {
self.keys.len()
}
fn validity(&self) -> Option<&MutableBitmap> {
self.keys.validity()
}
fn as_box(&mut self) -> Box<dyn Array> {
Box::new(self.take_into())
}
fn as_arc(&mut self) -> Arc<dyn Array> {
Arc::new(self.take_into())
}
fn data_type(&self) -> &DataType {
&self.data_type
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
self
}
fn push_null(&mut self) {
self.keys.push(None)
}
fn reserve(&mut self, additional: usize) {
self.reserve(additional)
}
fn shrink_to_fit(&mut self) {
self.shrink_to_fit()
}
}
impl<K, M, T> TryExtend<Option<T>> for MutableDictionaryArray<K, M>
where
K: DictionaryKey,
M: MutableArray + Indexable + TryExtend<Option<T>>,
T: AsIndexed<M>,
M::Type: Eq + Hash,
{
fn try_extend<II: IntoIterator<Item = Option<T>>>(&mut self, iter: II) -> Result<()> {
for value in iter {
if let Some(value) = value {
let key = self
.map
.try_push_valid(value, |arr, v| arr.try_extend(std::iter::once(Some(v))))?;
self.keys.try_push(Some(key))?;
} else {
self.push_null();
}
}
Ok(())
}
}
impl<K, M, T> TryPush<Option<T>> for MutableDictionaryArray<K, M>
where
K: DictionaryKey,
M: MutableArray + Indexable + TryPush<Option<T>>,
T: AsIndexed<M>,
M::Type: Eq + Hash,
{
fn try_push(&mut self, item: Option<T>) -> Result<()> {
if let Some(value) = item {
let key = self
.map
.try_push_valid(value, |arr, v| arr.try_push(Some(v)))?;
self.keys.try_push(Some(key))?;
} else {
self.push_null();
}
Ok(())
}
}