vortex_array/
implementation.rsuse vortex_buffer::Buffer;
use vortex_error::{vortex_bail, VortexError, VortexExpect as _, VortexResult};
use crate::array::visitor::ArrayVisitor;
use crate::encoding::{ArrayEncoding, ArrayEncodingExt, ArrayEncodingRef, EncodingId, EncodingRef};
use crate::stats::ArrayStatistics;
use crate::{
    Array, ArrayDType, ArrayData, ArrayMetadata, ArrayTrait, GetArrayMetadata, Inner, IntoArray,
    ToArrayData, TryDeserializeArrayMetadata,
};
pub trait ArrayDef {
    const ID: EncodingId;
    const ENCODING: EncodingRef;
    type Array: ArrayTrait + TryFrom<Array, Error = VortexError>;
    type Metadata: ArrayMetadata + Clone + for<'m> TryDeserializeArrayMetadata<'m>;
    type Encoding: ArrayEncoding + ArrayEncodingExt<D = Self>;
}
#[macro_export]
macro_rules! impl_encoding {
    ($id:literal, $code:expr, $Name:ident) => {
        $crate::paste::paste! {
            #[derive(std::fmt::Debug, Clone)]
            pub struct $Name;
            impl $crate::ArrayDef for $Name {
                const ID: $crate::encoding::EncodingId = $crate::encoding::EncodingId::new($id, $code);
                const ENCODING: $crate::encoding::EncodingRef = &[<$Name Encoding>];
                type Array = [<$Name Array>];
                type Metadata = [<$Name Metadata>];
                type Encoding = [<$Name Encoding>];
            }
            #[derive(std::fmt::Debug, Clone)]
            pub struct [<$Name Array>] {
                typed: $crate::TypedArray<$Name>
            }
            impl AsRef<$crate::Array> for [<$Name Array>] {
                fn as_ref(&self) -> &$crate::Array {
                    self.typed.array()
                }
            }
            impl [<$Name Array>] {
                #[allow(clippy::same_name_method)]
                fn metadata(&self) -> &[<$Name Metadata>] {
                    self.typed.metadata()
                }
                pub fn len(&self) -> usize {
                    self.typed.array().len()
                }
                pub fn is_empty(&self) -> bool {
                    self.typed.array().is_empty()
                }
                #[allow(dead_code)]
                fn try_from_parts(
                    dtype: vortex_dtype::DType,
                    len: usize,
                    metadata: [<$Name Metadata>],
                    children: std::sync::Arc<[$crate::Array]>,
                    stats: $crate::stats::StatsSet,
                ) -> VortexResult<Self> {
                    Ok(Self { typed: $crate::TypedArray::try_from_parts(dtype, len, metadata, None, children, stats)? })
                }
            }
            impl $crate::GetArrayMetadata for [<$Name Array>] {
                #[allow(clippy::same_name_method)]
                fn metadata(&self) -> std::sync::Arc<dyn $crate::ArrayMetadata> {
                    std::sync::Arc::new(self.metadata().clone())
                }
            }
            impl $crate::ToArray for [<$Name Array>] {
                fn to_array(&self) -> $crate::Array {
                    self.typed.to_array()
                }
            }
            impl $crate::IntoArray for [<$Name Array>] {
                fn into_array(self) -> $crate::Array {
                    self.typed.into_array()
                }
            }
            impl From<$crate::TypedArray<$Name>> for [<$Name Array>] {
                fn from(typed: $crate::TypedArray<$Name>) -> Self {
                    Self { typed }
                }
            }
            impl TryFrom<$crate::Array> for [<$Name Array>] {
                type Error = vortex_error::VortexError;
                #[inline]
                fn try_from(array: $crate::Array) -> Result<Self, Self::Error> {
                    $crate::TypedArray::<$Name>::try_from(array).map(Self::from)
                }
            }
            impl TryFrom<&$crate::Array> for [<$Name Array>] {
                type Error = vortex_error::VortexError;
                #[inline]
                fn try_from(array: &$crate::Array) -> Result<Self, Self::Error> {
                    $crate::TypedArray::<$Name>::try_from(array).map(Self::from)
                }
            }
            impl From<[<$Name Array>]> for $crate::Array {
                fn from(value: [<$Name Array>]) -> $crate::Array {
                    use $crate::IntoArray;
                    value.typed.into_array()
                }
            }
            #[derive(std::fmt::Debug)]
            pub struct [<$Name Encoding>];
            impl $crate::encoding::ArrayEncoding for [<$Name Encoding>] {
                #[inline]
                fn id(&self) -> $crate::encoding::EncodingId {
                    <$Name as $crate::ArrayDef>::ID
                }
                #[inline]
                fn canonicalize(&self, array: $crate::Array) -> vortex_error::VortexResult<$crate::Canonical> {
                    <Self as $crate::encoding::ArrayEncodingExt>::into_canonical(array)
                }
                #[inline]
                fn with_dyn(
                    &self,
                    array: &$crate::Array,
                    f: &mut dyn for<'b> FnMut(&'b (dyn $crate::ArrayTrait + 'b)) -> vortex_error::VortexResult<()>,
                ) -> vortex_error::VortexResult<()> {
                    <Self as $crate::encoding::ArrayEncodingExt>::with_dyn(array, f)
                }
            }
            impl $crate::encoding::ArrayEncodingExt for [<$Name Encoding>] {
                type D = $Name;
            }
            impl $crate::ArrayMetadata for [<$Name Metadata>] {
                #[inline]
                fn as_any(&self) -> &dyn std::any::Any {
                    self
                }
                #[inline]
                fn as_any_arc(self: std::sync::Arc<Self>) -> std::sync::Arc<dyn std::any::Any + std::marker::Send + std::marker::Sync> {
                    self
                }
            }
        }
    };
}
impl<T: AsRef<Array>> ArrayEncodingRef for T {
    fn encoding(&self) -> EncodingRef {
        self.as_ref().encoding()
    }
}
impl<D> ToArrayData for D
where
    D: IntoArray + ArrayEncodingRef + ArrayStatistics + GetArrayMetadata + Clone,
{
    fn to_array_data(&self) -> ArrayData {
        let array = self.clone().into_array();
        match array.0 {
            Inner::Data(d) => d,
            Inner::View(ref view) => {
                struct Visitor {
                    buffer: Option<Buffer>,
                    children: Vec<Array>,
                }
                impl ArrayVisitor for Visitor {
                    fn visit_child(&mut self, _name: &str, array: &Array) -> VortexResult<()> {
                        self.children.push(array.clone());
                        Ok(())
                    }
                    fn visit_buffer(&mut self, buffer: &Buffer) -> VortexResult<()> {
                        if self.buffer.is_some() {
                            vortex_bail!("Multiple buffers found in view")
                        }
                        self.buffer = Some(buffer.clone());
                        Ok(())
                    }
                }
                let mut visitor = Visitor {
                    buffer: None,
                    children: vec![],
                };
                array.with_dyn(|a| {
                    a.accept(&mut visitor)
                        .vortex_expect("Error while visiting Array View children")
                });
                ArrayData::try_new(
                    view.encoding(),
                    array.dtype().clone(),
                    array.len(),
                    self.metadata(),
                    visitor.buffer,
                    visitor.children.into(),
                    view.statistics().to_set(),
                )
                .vortex_expect("Failed to create ArrayData from Array View")
            }
        }
    }
}
impl AsRef<Array> for Array {
    fn as_ref(&self) -> &Array {
        self
    }
}