1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::sync::{Arc, OnceLock};

use vortex_buffer::Buffer;
use vortex_dtype::DType;
use vortex_error::{vortex_bail, VortexError, VortexResult};

use crate::stats::StatsSet;
use crate::{Array, ArrayData, ArrayDef, AsArray, IntoArray, ToArray, TryDeserializeArrayMetadata};

#[derive(Debug, Clone)]
pub struct TypedArray<D: ArrayDef> {
    array: Array,
    lazy_metadata: OnceLock<D::Metadata>,
}

impl<D: ArrayDef> TypedArray<D> {
    pub fn try_from_parts(
        dtype: DType,
        len: usize,
        metadata: D::Metadata,
        buffer: Option<Buffer>,
        children: Arc<[Array]>,
        stats: StatsSet,
    ) -> VortexResult<Self> {
        let array = Array::Data(ArrayData::try_new(
            D::ENCODING,
            dtype,
            len,
            Arc::new(metadata),
            buffer,
            children,
            stats,
        )?);
        Ok(Self {
            array,
            lazy_metadata: OnceLock::new(),
        })
    }

    pub fn metadata(&self) -> &D::Metadata {
        match &self.array {
            Array::Data(d) => d.metadata().as_any().downcast_ref::<D::Metadata>().unwrap(),
            Array::View(v) => self
                .lazy_metadata
                .get_or_init(|| D::Metadata::try_deserialize_metadata(v.metadata()).unwrap()),
        }
    }
}

impl<D: ArrayDef> TypedArray<D> {
    pub fn array(&self) -> &Array {
        &self.array
    }
}

impl<D: ArrayDef> TryFrom<Array> for TypedArray<D> {
    type Error = VortexError;

    fn try_from(array: Array) -> Result<Self, Self::Error> {
        if array.encoding().id() != D::ENCODING.id() {
            vortex_bail!(
                "incorrect encoding {}, expected {}",
                array.encoding().id().as_ref(),
                D::ENCODING.id().as_ref(),
            );
        }
        Ok(Self {
            array,
            lazy_metadata: OnceLock::new(),
        })
    }
}

impl<'a, D: ArrayDef> TryFrom<&'a Array> for TypedArray<D> {
    type Error = VortexError;

    fn try_from(value: &'a Array) -> Result<Self, Self::Error> {
        value.clone().try_into()
    }
}

impl<D: ArrayDef> AsArray for TypedArray<D> {
    fn as_array_ref(&self) -> &Array {
        &self.array
    }
}

impl<D: ArrayDef> ToArray for TypedArray<D> {
    fn to_array(&self) -> Array {
        self.array.clone()
    }
}

impl<D: ArrayDef> IntoArray for TypedArray<D> {
    fn into_array(self) -> Array {
        self.array
    }
}