cfpyo3_core/df/
meta.rs

1use super::{DataFrame, DataFrameView, OwnedDataFrame};
2use crate::{
3    df::{ColumnsDtype, IndexDtype},
4    toolkit::array::AFloat,
5};
6use anyhow::Result;
7use numpy::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
8
9impl<'a, T: AFloat> DataFrame<'a, T> {
10    // constructors
11
12    pub fn new_view(
13        index: ArrayView1<'a, IndexDtype>,
14        columns: ArrayView1<'a, ColumnsDtype>,
15        values: ArrayView2<'a, T>,
16    ) -> Self {
17        Self::View(DataFrameView {
18            index,
19            columns,
20            values,
21        })
22    }
23    pub fn new_owned(
24        index: Array1<IndexDtype>,
25        columns: Array1<ColumnsDtype>,
26        values: Array2<T>,
27    ) -> Self {
28        Self::Owned(OwnedDataFrame {
29            index,
30            columns,
31            values,
32        })
33    }
34
35    /// # Safety
36    ///
37    /// This function requires that:
38    /// - pointers are aligned with [`DF_ALIGN`].
39    /// - pointers are representing the corresponding data types (i.e., [`IndexDtype`], [`ColumnsDtype`], and `T`).
40    /// - the 'owners' of the pointers should NOT be freed before the [`DataFrame`] is dropped.
41    pub unsafe fn from_ptr(
42        index_ptr: *const u8,
43        index_shape: usize,
44        columns_ptr: *const u8,
45        columns_shape: usize,
46        values_ptr: *const u8,
47    ) -> Self {
48        let index = ArrayView1::<IndexDtype>::from_shape_ptr(
49            (index_shape,),
50            index_ptr as *const IndexDtype,
51        );
52        let columns = ArrayView1::<ColumnsDtype>::from_shape_ptr(
53            (columns_shape,),
54            columns_ptr as *const ColumnsDtype,
55        );
56        let values =
57            ArrayView2::<T>::from_shape_ptr((index_shape, columns_shape), values_ptr as *const T);
58        Self::new_view(index, columns, values)
59    }
60    pub fn from_vec(
61        index: Vec<IndexDtype>,
62        columns: Vec<ColumnsDtype>,
63        values: Vec<T>,
64    ) -> Result<Self> {
65        let index_shape = index.len();
66        let columns_shape = columns.len();
67        Ok(Self::new_owned(
68            Array1::from_shape_vec((index_shape,), index)?,
69            Array1::from_shape_vec((columns_shape,), columns)?,
70            Array2::from_shape_vec((index_shape, columns_shape), values)?,
71        ))
72    }
73
74    // getters
75
76    pub fn index(&self) -> ArrayView1<IndexDtype> {
77        match self {
78            Self::View(df) => df.index.view(),
79            Self::Owned(df) => df.index.view(),
80        }
81    }
82    pub fn columns(&self) -> ArrayView1<ColumnsDtype> {
83        match self {
84            Self::View(df) => df.columns.view(),
85            Self::Owned(df) => df.columns.view(),
86        }
87    }
88    pub fn values(&self) -> ArrayView2<T> {
89        match self {
90            Self::View(df) => df.values.view(),
91            Self::Owned(df) => df.values.view(),
92        }
93    }
94
95    pub fn is_owned(&self) -> bool {
96        matches!(self, Self::Owned(_))
97    }
98    pub fn into_owned(self) -> Self {
99        match self {
100            Self::Owned(df) => Self::Owned(df),
101            Self::View(df) => Self::new_owned(
102                df.index.to_owned(),
103                df.columns.to_owned(),
104                df.values.to_owned(),
105            ),
106        }
107    }
108}
109
110pub const DF_ALIGN: usize = align_of::<DataFrame<f64>>();
111pub fn align_nbytes(nbytes: usize) -> usize {
112    let remainder = nbytes % DF_ALIGN;
113    if remainder == 0 {
114        nbytes
115    } else {
116        nbytes + DF_ALIGN - remainder
117    }
118}