Skip to main content

essentia_core/data/
conversion_get.rs

1use essentia_sys::ffi;
2use ndarray::{Array2, Array4};
3use std::collections::HashMap;
4
5use crate::{ConversionError, DataContainer, Pool, phantom};
6
7pub trait GetFromDataContainer<T> {
8    fn get(&self) -> T;
9}
10
11pub trait TryGetFromDataContainer<T> {
12    fn try_get(&self) -> Result<T, ConversionError>;
13}
14
15impl<'a> GetFromDataContainer<bool> for DataContainer<'a, phantom::Bool> {
16    fn get(&self) -> bool {
17        self.inner.as_ref().get_bool().unwrap()
18    }
19}
20
21impl<'a> GetFromDataContainer<String> for DataContainer<'a, phantom::String> {
22    fn get(&self) -> String {
23        self.inner.as_ref().get_string().unwrap().to_string()
24    }
25}
26
27impl<'a> GetFromDataContainer<i32> for DataContainer<'a, phantom::Int> {
28    fn get(&self) -> i32 {
29        self.inner.as_ref().get_int().unwrap()
30    }
31}
32
33impl<'a> GetFromDataContainer<f32> for DataContainer<'a, phantom::Float> {
34    fn get(&self) -> f32 {
35        self.inner.as_ref().get_float().unwrap()
36    }
37}
38
39impl<'a> GetFromDataContainer<u32> for DataContainer<'a, phantom::UnsignedInt> {
40    fn get(&self) -> u32 {
41        self.inner.as_ref().get_unsigned_int().unwrap()
42    }
43}
44
45impl<'a> GetFromDataContainer<i64> for DataContainer<'a, phantom::Long> {
46    fn get(&self) -> i64 {
47        self.inner.as_ref().get_long().unwrap()
48    }
49}
50
51impl<'a> GetFromDataContainer<ffi::StereoSample> for DataContainer<'a, phantom::StereoSample> {
52    fn get(&self) -> ffi::StereoSample {
53        self.inner.as_ref().get_stereo_sample().unwrap()
54    }
55}
56
57impl<'a> GetFromDataContainer<num::Complex<f32>> for DataContainer<'a, phantom::Complex> {
58    fn get(&self) -> num::Complex<f32> {
59        let ffi_complex = self.inner.as_ref().get_complex().unwrap();
60        num::Complex::new(ffi_complex.real, ffi_complex.imag)
61    }
62}
63
64impl<'a> GetFromDataContainer<Array4<f32>> for DataContainer<'a, phantom::TensorFloat> {
65    fn get(&self) -> Array4<f32> {
66        let tensor = self.inner.as_ref().get_tensor_float().unwrap();
67
68        let shape = (
69            tensor.shape[0],
70            tensor.shape[1],
71            tensor.shape[2],
72            tensor.shape[3],
73        );
74
75        Array4::from_shape_vec(shape, tensor.slice.to_vec()).unwrap() // Safe because C++ guarantees correct dimensions
76    }
77}
78
79impl<'a> GetFromDataContainer<Vec<bool>> for DataContainer<'a, phantom::VectorBool> {
80    fn get(&self) -> Vec<bool> {
81        self.inner.as_ref().get_vector_bool().unwrap()
82    }
83}
84
85impl<'a> GetFromDataContainer<Vec<i32>> for DataContainer<'a, phantom::VectorInt> {
86    fn get(&self) -> Vec<i32> {
87        self.inner.as_ref().get_vector_int().unwrap().to_vec()
88    }
89}
90
91impl<'a> GetFromDataContainer<Vec<String>> for DataContainer<'a, phantom::VectorString> {
92    fn get(&self) -> Vec<String> {
93        self.inner.as_ref().get_vector_string().unwrap()
94    }
95}
96
97impl<'a> GetFromDataContainer<Vec<f32>> for DataContainer<'a, phantom::VectorFloat> {
98    fn get(&self) -> Vec<f32> {
99        self.inner.as_ref().get_vector_float().unwrap().to_vec()
100    }
101}
102
103impl<'a> GetFromDataContainer<Vec<ffi::StereoSample>>
104    for DataContainer<'a, phantom::VectorStereoSample>
105{
106    fn get(&self) -> Vec<ffi::StereoSample> {
107        self.inner
108            .as_ref()
109            .get_vector_stereo_sample()
110            .unwrap()
111            .to_vec()
112    }
113}
114
115impl<'a> GetFromDataContainer<Vec<num::Complex<f32>>>
116    for DataContainer<'a, phantom::VectorComplex>
117{
118    fn get(&self) -> Vec<num::Complex<f32>> {
119        self.inner
120            .as_ref()
121            .get_vector_complex()
122            .unwrap()
123            .iter()
124            .map(|c| num::Complex::new(c.real, c.imag))
125            .collect()
126    }
127}
128
129impl<'a> GetFromDataContainer<Array2<f32>> for DataContainer<'a, phantom::MatrixFloat> {
130    fn get(&self) -> Array2<f32> {
131        let matrix_float = self.inner.as_ref().get_matrix_float().unwrap();
132
133        Array2::from_shape_vec(
134            (matrix_float.dim1, matrix_float.dim2),
135            matrix_float.slice.to_vec(),
136        )
137        .unwrap() // Safe because C++ guarantees correct dimensions
138    }
139}
140
141impl<'a> GetFromDataContainer<Vec<Array2<f32>>> for DataContainer<'a, phantom::VectorMatrixFloat> {
142    fn get(&self) -> Vec<Array2<f32>> {
143        let matrices = self.inner.as_ref().get_vector_matrix_float().unwrap();
144
145        matrices
146            .into_iter()
147            .map(|matrix_float| {
148                Array2::from_shape_vec(
149                    (matrix_float.dim1, matrix_float.dim2),
150                    matrix_float.slice.to_vec(),
151                )
152                .unwrap() // Safe because C++ guarantees correct dimensions
153            })
154            .collect()
155    }
156}
157
158impl<'a> GetFromDataContainer<Vec<Vec<f32>>> for DataContainer<'a, phantom::VectorVectorFloat> {
159    fn get(&self) -> Vec<Vec<f32>> {
160        self.inner
161            .as_ref()
162            .get_vector_vector_float()
163            .unwrap()
164            .into_iter()
165            .map(|float_slice| float_slice.slice.to_vec())
166            .collect()
167    }
168}
169
170impl<'a> TryGetFromDataContainer<Array2<f32>> for DataContainer<'a, phantom::VectorVectorFloat> {
171    fn try_get(&self) -> Result<Array2<f32>, ConversionError> {
172        let vec_vec_data = self.inner.as_ref().get_vector_vector_float().unwrap();
173
174        if vec_vec_data.is_empty() {
175            return Err(ConversionError::InvalidFormat {
176                message: "Cannot create matrix from empty vector".to_string(),
177            });
178        }
179
180        let expected_cols = vec_vec_data[0].slice.len();
181        if expected_cols == 0 {
182            return Err(ConversionError::InvalidFormat {
183                message: "Cannot create matrix from empty rows".to_string(),
184            });
185        }
186
187        for (row_idx, row_data) in vec_vec_data.iter().enumerate() {
188            if row_data.slice.len() != expected_cols {
189                return Err(ConversionError::InvalidFormat {
190                    message: format!(
191                        "Non-rectangular matrix: row {} has {} elements, expected {}",
192                        row_idx,
193                        row_data.slice.len(),
194                        expected_cols
195                    ),
196                });
197            }
198        }
199
200        let mut flat_data = Vec::with_capacity(vec_vec_data.len() * expected_cols);
201        for row_data in &vec_vec_data {
202            flat_data.extend_from_slice(row_data.slice);
203        }
204
205        let dim1 = vec_vec_data.len();
206        let dim2 = expected_cols;
207
208        Ok(Array2::from_shape_vec((dim1, dim2), flat_data).unwrap())
209    }
210}
211
212impl<'a> GetFromDataContainer<Vec<Vec<String>>> for DataContainer<'a, phantom::VectorVectorString> {
213    fn get(&self) -> Vec<Vec<String>> {
214        self.inner
215            .as_ref()
216            .get_vector_vector_string()
217            .unwrap()
218            .into_iter()
219            .map(|vec_string| vec_string.vec)
220            .collect()
221    }
222}
223
224impl<'a> GetFromDataContainer<Vec<Vec<ffi::StereoSample>>>
225    for DataContainer<'a, phantom::VectorVectorStereoSample>
226{
227    fn get(&self) -> Vec<Vec<ffi::StereoSample>> {
228        self.inner
229            .as_ref()
230            .get_vector_vector_stereo_sample()
231            .unwrap()
232            .into_iter()
233            .map(|slice_stereo_sample| slice_stereo_sample.slice.to_vec())
234            .collect()
235    }
236}
237
238impl<'a> GetFromDataContainer<Vec<Vec<num::Complex<f32>>>>
239    for DataContainer<'a, phantom::VectorVectorComplex>
240{
241    fn get(&self) -> Vec<Vec<num::Complex<f32>>> {
242        self.inner
243            .as_ref()
244            .get_vector_vector_complex()
245            .unwrap()
246            .into_iter()
247            .map(|vec_complex| {
248                vec_complex
249                    .vec
250                    .into_iter()
251                    .map(|c| num::Complex::new(c.real, c.imag))
252                    .collect()
253            })
254            .collect()
255    }
256}
257
258impl<'a> GetFromDataContainer<HashMap<String, f32>> for DataContainer<'a, phantom::MapFloat> {
259    fn get(&self) -> HashMap<String, f32> {
260        self.inner
261            .as_ref()
262            .get_map_float()
263            .unwrap()
264            .into_iter()
265            .map(|entry| (entry.key.to_string(), entry.value))
266            .collect()
267    }
268}
269
270impl<'a> GetFromDataContainer<HashMap<String, Vec<f32>>>
271    for DataContainer<'a, phantom::MapVectorFloat>
272{
273    fn get(&self) -> HashMap<String, Vec<f32>> {
274        self.inner
275            .as_ref()
276            .get_map_vector_float()
277            .unwrap()
278            .into_iter()
279            .map(|entry| (entry.key.to_string(), entry.value.to_vec()))
280            .collect()
281    }
282}
283
284impl<'a> GetFromDataContainer<HashMap<String, Vec<String>>>
285    for DataContainer<'a, phantom::MapVectorString>
286{
287    fn get(&self) -> HashMap<String, Vec<String>> {
288        self.inner
289            .as_ref()
290            .get_map_vector_string()
291            .unwrap()
292            .into_iter()
293            .map(|entry| (entry.key.to_string(), entry.value))
294            .collect()
295    }
296}
297
298impl<'a> GetFromDataContainer<HashMap<String, Vec<i32>>>
299    for DataContainer<'a, phantom::MapVectorInt>
300{
301    fn get(&self) -> HashMap<String, Vec<i32>> {
302        self.inner
303            .as_ref()
304            .get_map_vector_int()
305            .unwrap()
306            .into_iter()
307            .map(|entry| (entry.key.to_string(), entry.value.to_vec()))
308            .collect()
309    }
310}
311
312impl<'a> GetFromDataContainer<HashMap<String, Vec<num::Complex<f32>>>>
313    for DataContainer<'a, phantom::MapVectorComplex>
314{
315    fn get(&self) -> HashMap<String, Vec<num::Complex<f32>>> {
316        self.inner
317            .as_ref()
318            .get_map_vector_complex()
319            .unwrap()
320            .into_iter()
321            .map(|entry| {
322                (
323                    entry.key.to_string(),
324                    entry
325                        .value
326                        .iter()
327                        .map(|c| num::Complex::new(c.real, c.imag))
328                        .collect(),
329                )
330            })
331            .collect()
332    }
333}
334
335// TODO Maybe the Pool should be take a reference to the PoolBridge?
336impl<'a> GetFromDataContainer<Pool> for DataContainer<'a, phantom::Pool> {
337    fn get(&self) -> Pool {
338        let pool_bridge_ref = self.inner.as_ref().get_pool();
339        let cloned_bridge = pool_bridge_ref.clone();
340        Pool::new_from_bridge(cloned_bridge)
341    }
342}