Skip to main content

essentia_core/data/
container.rs

1use cxx::UniquePtr;
2use essentia_sys::ffi;
3use std::marker::PhantomData;
4use thiserror::Error;
5
6use super::types::{DataType, HasDataType};
7
8pub enum DataContainerInner<'a> {
9    Owned(UniquePtr<ffi::DataContainer>),
10    Borrowed(&'a ffi::DataContainer),
11}
12
13impl<'a> AsRef<ffi::DataContainer> for DataContainerInner<'a> {
14    fn as_ref(&self) -> &ffi::DataContainer {
15        match self {
16            DataContainerInner::Owned(ptr) => ptr.as_ref().expect("UniquePtr should not be null"),
17            DataContainerInner::Borrowed(reference) => reference,
18        }
19    }
20}
21
22pub struct DataContainer<'a, T> {
23    pub(crate) inner: DataContainerInner<'a>,
24    _marker: PhantomData<T>,
25}
26
27impl<'a, T> DataContainer<'a, T> {
28    pub(crate) fn new_owned(inner: UniquePtr<ffi::DataContainer>) -> Self {
29        Self {
30            inner: DataContainerInner::Owned(inner),
31            _marker: PhantomData,
32        }
33    }
34
35    pub(crate) fn new_borrowed(inner: &'a ffi::DataContainer) -> Self {
36        Self {
37            inner: DataContainerInner::Borrowed(inner),
38            _marker: PhantomData,
39        }
40    }
41
42    pub fn into_any(self) -> DataContainer<'a, super::types::phantom::Any> {
43        DataContainer {
44            inner: self.inner,
45            _marker: PhantomData,
46        }
47    }
48
49    pub fn data_type(&self) -> DataType {
50        self.inner.as_ref().get_data_type().into()
51    }
52
53    pub fn into_owned_ptr(self) -> UniquePtr<ffi::DataContainer> {
54        match self.inner {
55            DataContainerInner::Owned(ptr) => ptr,
56            DataContainerInner::Borrowed(borrowed) => copy_to_owned(borrowed),
57        }
58    }
59}
60
61impl<'a, T: HasDataType> DataContainer<'a, T> {
62    pub fn compile_time_data_type() -> DataType {
63        T::data_type()
64    }
65
66    pub fn verify_type(&self) -> Result<(), TypeMismatchError> {
67        let runtime_type = self.data_type();
68        let compile_time_type = Self::compile_time_data_type();
69
70        if runtime_type == compile_time_type {
71            Ok(())
72        } else {
73            Err(TypeMismatchError {
74                expected: compile_time_type,
75                actual: runtime_type,
76            })
77        }
78    }
79}
80
81#[derive(Debug, Clone, PartialEq, Error)]
82#[error("Type mismatch: expected {expected}, got {actual}")]
83pub struct TypeMismatchError {
84    pub expected: DataType,
85    pub actual: DataType,
86}
87
88fn copy_to_owned(data: &ffi::DataContainer) -> UniquePtr<ffi::DataContainer> {
89    let data_type = data.get_data_type();
90
91    match data_type {
92        ffi::DataType::Bool => {
93            let value = data.get_bool().unwrap();
94            ffi::create_data_container_from_bool(value)
95        }
96        ffi::DataType::String => {
97            let value = data.get_string().unwrap();
98            ffi::create_data_container_from_string(&value)
99        }
100        ffi::DataType::Float => {
101            let value = data.get_float().unwrap();
102            ffi::create_data_container_from_float(value)
103        }
104        ffi::DataType::Int => {
105            let value = data.get_int().unwrap();
106            ffi::create_data_container_from_int(value)
107        }
108        ffi::DataType::UnsignedInt => {
109            let value = data.get_unsigned_int().unwrap();
110            ffi::create_data_container_from_unsigned_int(value)
111        }
112        ffi::DataType::Long => {
113            let value = data.get_long().unwrap();
114            ffi::create_data_container_from_long(value)
115        }
116        ffi::DataType::StereoSample => {
117            let value = data.get_stereo_sample().unwrap();
118            ffi::create_data_container_from_stereo_sample(value)
119        }
120        ffi::DataType::VectorBool => {
121            let value = data.get_vector_bool().unwrap();
122            ffi::create_data_container_from_vector_bool(&value)
123        }
124        ffi::DataType::VectorInt => {
125            let value = data.get_vector_int().unwrap();
126            ffi::create_data_container_from_vector_int(value)
127        }
128        ffi::DataType::VectorString => {
129            let strings = data.get_vector_string().unwrap();
130            let str_refs: Vec<&str> = strings.iter().map(|s| s.as_str()).collect();
131            ffi::create_data_container_from_vector_string(&str_refs)
132        }
133        ffi::DataType::VectorFloat => {
134            let value = data.get_vector_float().unwrap();
135            ffi::create_data_container_from_vector_float(value)
136        }
137        ffi::DataType::VectorStereoSample => {
138            let value = data.get_vector_stereo_sample().unwrap();
139            ffi::create_data_container_from_vector_stereo_sample(value)
140        }
141        ffi::DataType::VectorVectorFloat => {
142            let value = data.get_vector_vector_float().unwrap();
143            ffi::create_data_container_from_vector_vector_float(value)
144        }
145        ffi::DataType::MatrixFloat => {
146            let value = data.get_matrix_float().unwrap();
147            ffi::create_data_container_from_matrix_float(value)
148        }
149        ffi::DataType::VectorVectorString => {
150            let value = data.get_vector_vector_string().unwrap();
151            ffi::create_data_container_from_vector_vector_string(value)
152        }
153        ffi::DataType::VectorVectorStereoSample => {
154            let value = data.get_vector_vector_stereo_sample().unwrap();
155            ffi::create_data_container_from_vector_vector_stereo_sample(value)
156        }
157        ffi::DataType::VectorMatrixFloat => {
158            let value = data.get_vector_matrix_float().unwrap();
159            ffi::create_data_container_from_vector_matrix_float(value)
160        }
161        ffi::DataType::MapVectorFloat => {
162            let value = data.get_map_vector_float().unwrap();
163            ffi::create_data_container_from_map_vector_float(value)
164        }
165        ffi::DataType::MapVectorString => {
166            let value = data.get_map_vector_string().unwrap();
167            ffi::create_data_container_from_map_vector_string(value)
168        }
169        ffi::DataType::MapVectorInt => {
170            let value = data.get_map_vector_int().unwrap();
171            ffi::create_data_container_from_map_vector_int(value)
172        }
173        ffi::DataType::MapFloat => {
174            let value = data.get_map_float().unwrap();
175            ffi::create_data_container_from_map_float(value)
176        }
177        ffi::DataType::Pool => {
178            let pool_bridge_ref = data.get_pool();
179            let cloned_pool = pool_bridge_ref.clone();
180            ffi::create_data_container_from_pool(cloned_pool)
181        }
182        data_type => {
183            panic!(
184                "Unsupported data type: {:?}. This indicates a bug - the Rust code is out of sync with the C++ data types.",
185                data_type
186            )
187        }
188    }
189}