essentia_core/pool/
pool.rs1use cxx::UniquePtr;
2use essentia_sys::ffi;
3use thiserror::Error;
4
5use crate::data::types::HasDataType;
6use crate::data::{
7 ConversionError, DataContainer, DataType, GetFromDataContainer, PoolData, TryIntoDataContainer,
8};
9
10pub struct Pool {
11 inner: UniquePtr<ffi::PoolBridge>,
12}
13
14impl Default for Pool {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl Pool {
21 pub fn new() -> Self {
22 Self {
23 inner: ffi::create_pool_bridge(),
24 }
25 }
26
27 pub(crate) fn new_from_bridge(bridge: UniquePtr<ffi::PoolBridge>) -> Self {
28 Self { inner: bridge }
29 }
30
31 pub fn set<T>(
32 &mut self,
33 key: &str,
34 value: impl TryIntoDataContainer<T>,
35 ) -> Result<(), PoolError>
36 where
37 T: PoolData + HasDataType,
38 {
39 let data_container =
40 value
41 .try_into_data_container()
42 .map_err(|error| PoolError::DataConversion {
43 key: key.to_string(),
44 source: error,
45 })?;
46
47 self.inner
48 .pin_mut()
49 .set(key, data_container.into_owned_ptr());
50
51 Ok(())
52 }
53
54 pub fn get<T, R>(&self, key: &str) -> Result<R, PoolError>
55 where
56 T: PoolData + HasDataType,
57 for<'a> DataContainer<'a, T>: GetFromDataContainer<R>,
58 {
59 if !self.contains(key) {
60 return Err(PoolError::KeyNotFound {
61 key: key.to_string(),
62 });
63 }
64
65 let data_container_ffi =
66 self.inner
67 .as_ref()
68 .unwrap()
69 .get(key)
70 .map_err(|exception| PoolError::Internal {
71 key: key.to_string(),
72 source: exception,
73 })?;
74
75 let data_container = DataContainer::new_borrowed(data_container_ffi.as_ref().unwrap());
76
77 let expected_type = T::data_type();
79 let actual_type = data_container.data_type();
80
81 if actual_type != expected_type {
82 return Err(PoolError::TypeMismatch {
83 key: key.to_string(),
84 expected: expected_type,
85 actual: actual_type,
86 });
87 }
88
89 Ok(data_container.get())
90 }
91
92 pub fn get_container<T>(&self, key: &str) -> Result<DataContainer<'static, T>, PoolError>
93 where
94 T: PoolData + HasDataType,
95 {
96 if !self.contains(key) {
97 return Err(PoolError::KeyNotFound {
98 key: key.to_string(),
99 });
100 }
101
102 let data_container_ffi =
103 self.inner
104 .as_ref()
105 .unwrap()
106 .get(key)
107 .map_err(|exception| PoolError::Internal {
108 key: key.to_string(),
109 source: exception,
110 })?;
111
112 let data_container = DataContainer::new_owned(data_container_ffi);
113
114 let expected_type = T::data_type();
116 let actual_type = data_container.data_type();
117
118 if actual_type != expected_type {
119 return Err(PoolError::TypeMismatch {
120 key: key.to_string(),
121 expected: expected_type,
122 actual: actual_type,
123 });
124 }
125
126 Ok(data_container)
127 }
128
129 pub fn contains(&self, key: &str) -> bool {
130 self.inner.as_ref().unwrap().contains(key)
131 }
132
133 pub fn keys(&self) -> Vec<String> {
134 self.inner.as_ref().unwrap().keys()
135 }
136
137 pub fn len(&self) -> usize {
138 self.keys().len()
139 }
140
141 pub fn is_empty(&self) -> bool {
142 self.len() == 0
143 }
144
145 pub(crate) fn into_owned_ptr(self) -> UniquePtr<ffi::PoolBridge> {
146 self.inner
147 }
148}
149
150#[derive(Debug, Error)]
151pub enum PoolError {
152 #[error("Key '{key}' not found in pool")]
153 KeyNotFound { key: String },
154
155 #[error("Type mismatch for key '{key}': expected {expected}, found {actual}")]
156 TypeMismatch {
157 key: String,
158 expected: DataType,
159 actual: DataType,
160 },
161
162 #[error("Failed to convert data for key '{key}': {source}")]
163 DataConversion {
164 key: String,
165 #[source]
166 source: ConversionError,
167 },
168
169 #[error("Internal error for key '{key}': {source}")]
170 Internal {
171 key: String,
172 #[source]
173 source: cxx::Exception,
174 },
175}