essentia_core/data/
container.rs1use 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}