1use std::ffi::{CStr, CString};
5
6use crate::error::check_status;
7use crate::raw;
8use crate::{MlxArray, MlxCError};
9
10#[derive(Debug)]
12pub struct MlxMapStringToArray(raw::mlx_map_string_to_array);
13
14impl MlxMapStringToArray {
15 pub fn new() -> Result<Self, MlxCError> {
17 let operation: &'static str = "create an MLX string-to-array map";
18 let raw_map = unsafe { raw::mlx_map_string_to_array_new() };
20 if raw_map.ctx.is_null() {
21 return Err(MlxCError {
22 operation,
23 description: "MLX returned an empty map handle".to_owned(),
24 });
25 }
26 Ok(Self(raw_map))
27 }
28
29 pub fn set(&mut self, source: &Self) -> Result<(), MlxCError> {
31 let status = unsafe { raw::mlx_map_string_to_array_set(&mut self.0, source.0) };
34 check_status(status, "copy an MLX string-to-array map")
35 }
36
37 pub fn insert(&mut self, key: &str, value: &MlxArray) -> Result<(), MlxCError> {
39 let operation: &'static str = "insert into an MLX string-to-array map";
40 let key_argument = CString::new(key).map_err(|_| MlxCError {
41 operation,
42 description: "key contains an interior null byte".to_owned(),
43 })?;
44 let status = unsafe {
47 raw::mlx_map_string_to_array_insert(self.0, key_argument.as_ptr(), value.raw())
48 };
49 check_status(status, operation)
50 }
51
52 pub fn value_at(&self, key: &str) -> Result<Option<MlxArray>, MlxCError> {
54 let operation: &'static str = "read an MLX string-to-array map entry";
55 let key_argument = CString::new(key).map_err(|_| MlxCError {
56 operation,
57 description: "key contains an interior null byte".to_owned(),
58 })?;
59 let mut output = MlxArray::empty();
60 let status = unsafe {
63 raw::mlx_map_string_to_array_get(output.raw_mut(), self.0, key_argument.as_ptr())
64 };
65 check_status(status, operation)?;
66 if output.is_empty() {
67 return Ok(None);
68 }
69 Ok(Some(output))
70 }
71
72 pub fn iter(&self) -> Result<MlxMapStringToArrayIterator, MlxCError> {
74 let operation: &'static str = "iterate an MLX string-to-array map";
75 let raw_iterator = unsafe { raw::mlx_map_string_to_array_iterator_new(self.0) };
78 if raw_iterator.ctx.is_null() {
79 return Err(MlxCError {
80 operation,
81 description: "MLX returned an empty map iterator handle".to_owned(),
82 });
83 }
84 Ok(MlxMapStringToArrayIterator(raw_iterator))
85 }
86
87 pub(crate) const fn raw(&self) -> raw::mlx_map_string_to_array {
88 self.0
89 }
90
91 pub(crate) fn raw_mut(&mut self) -> *mut raw::mlx_map_string_to_array {
92 &mut self.0
93 }
94
95 pub(crate) fn from_borrowed_raw(raw_map: raw::mlx_map_string_to_array) -> Self {
97 Self(raw_map)
98 }
99}
100
101impl Drop for MlxMapStringToArray {
102 fn drop(&mut self) {
103 unsafe {
106 raw::mlx_map_string_to_array_free(self.0);
107 }
108 }
109}
110
111#[derive(Debug)]
113pub struct MlxMapStringToArrayIterator(raw::mlx_map_string_to_array_iterator);
114
115impl MlxMapStringToArrayIterator {
116 pub fn next_entry(&mut self) -> Result<Option<(String, MlxArray)>, MlxCError> {
118 let operation: &'static str = "advance an MLX string-to-array map iterator";
119 let mut key_pointer: *const std::os::raw::c_char = std::ptr::null();
120 let mut value = MlxArray::empty();
121 let status = unsafe {
124 raw::mlx_map_string_to_array_iterator_next(&mut key_pointer, value.raw_mut(), self.0)
125 };
126 check_status(status, operation)?;
127 if key_pointer.is_null() {
128 return Ok(None);
129 }
130 let key = unsafe { CStr::from_ptr(key_pointer) }
133 .to_string_lossy()
134 .into_owned();
135 Ok(Some((key, value)))
136 }
137}
138
139impl Drop for MlxMapStringToArrayIterator {
140 fn drop(&mut self) {
141 unsafe {
144 raw::mlx_map_string_to_array_iterator_free(self.0);
145 }
146 }
147}
148
149#[derive(Debug)]
151pub struct MlxMapStringToString(raw::mlx_map_string_to_string);
152
153impl MlxMapStringToString {
154 pub fn new() -> Result<Self, MlxCError> {
156 let operation: &'static str = "create an MLX string-to-string map";
157 let raw_map = unsafe { raw::mlx_map_string_to_string_new() };
159 if raw_map.ctx.is_null() {
160 return Err(MlxCError {
161 operation,
162 description: "MLX returned an empty map handle".to_owned(),
163 });
164 }
165 Ok(Self(raw_map))
166 }
167
168 pub fn set(&mut self, source: &Self) -> Result<(), MlxCError> {
170 let status = unsafe { raw::mlx_map_string_to_string_set(&mut self.0, source.0) };
173 check_status(status, "copy an MLX string-to-string map")
174 }
175
176 pub fn insert(&mut self, key: &str, value: &str) -> Result<(), MlxCError> {
178 let operation: &'static str = "insert into an MLX string-to-string map";
179 let key_argument = CString::new(key).map_err(|_| MlxCError {
180 operation,
181 description: "key contains an interior null byte".to_owned(),
182 })?;
183 let value_argument = CString::new(value).map_err(|_| MlxCError {
184 operation,
185 description: "value contains an interior null byte".to_owned(),
186 })?;
187 let status = unsafe {
189 raw::mlx_map_string_to_string_insert(
190 self.0,
191 key_argument.as_ptr(),
192 value_argument.as_ptr(),
193 )
194 };
195 check_status(status, operation)
196 }
197
198 pub fn value_at(&self, key: &str) -> Result<Option<String>, MlxCError> {
200 let operation: &'static str = "read an MLX string-to-string map entry";
201 let key_argument = CString::new(key).map_err(|_| MlxCError {
202 operation,
203 description: "key contains an interior null byte".to_owned(),
204 })?;
205 let mut value_pointer: *const std::os::raw::c_char = std::ptr::null();
206 let status = unsafe {
209 raw::mlx_map_string_to_string_get(&mut value_pointer, self.0, key_argument.as_ptr())
210 };
211 check_status(status, operation)?;
212 if value_pointer.is_null() {
213 return Ok(None);
214 }
215 let borrowed = unsafe { CStr::from_ptr(value_pointer) };
218 Ok(Some(borrowed.to_string_lossy().into_owned()))
219 }
220
221 pub fn iter(&self) -> Result<MlxMapStringToStringIterator, MlxCError> {
223 let operation: &'static str = "iterate an MLX string-to-string map";
224 let raw_iterator = unsafe { raw::mlx_map_string_to_string_iterator_new(self.0) };
227 if raw_iterator.ctx.is_null() {
228 return Err(MlxCError {
229 operation,
230 description: "MLX returned an empty map iterator handle".to_owned(),
231 });
232 }
233 Ok(MlxMapStringToStringIterator(raw_iterator))
234 }
235
236 pub(crate) const fn raw(&self) -> raw::mlx_map_string_to_string {
237 self.0
238 }
239
240 pub(crate) fn raw_mut(&mut self) -> *mut raw::mlx_map_string_to_string {
241 &mut self.0
242 }
243}
244
245impl Drop for MlxMapStringToString {
246 fn drop(&mut self) {
247 unsafe {
250 raw::mlx_map_string_to_string_free(self.0);
251 }
252 }
253}
254
255#[derive(Debug)]
257pub struct MlxMapStringToStringIterator(raw::mlx_map_string_to_string_iterator);
258
259impl MlxMapStringToStringIterator {
260 pub fn next_entry(&mut self) -> Result<Option<(String, String)>, MlxCError> {
262 let operation: &'static str = "advance an MLX string-to-string map iterator";
263 let mut key_pointer: *const std::os::raw::c_char = std::ptr::null();
264 let mut value_pointer: *const std::os::raw::c_char = std::ptr::null();
265 let status = unsafe {
268 raw::mlx_map_string_to_string_iterator_next(
269 &mut key_pointer,
270 &mut value_pointer,
271 self.0,
272 )
273 };
274 check_status(status, operation)?;
275 if key_pointer.is_null() {
276 return Ok(None);
277 }
278 let key = unsafe { CStr::from_ptr(key_pointer) }
281 .to_string_lossy()
282 .into_owned();
283 let value = if value_pointer.is_null() {
284 String::new()
285 } else {
286 unsafe { CStr::from_ptr(value_pointer) }
288 .to_string_lossy()
289 .into_owned()
290 };
291 Ok(Some((key, value)))
292 }
293}
294
295impl Drop for MlxMapStringToStringIterator {
296 fn drop(&mut self) {
297 unsafe {
300 raw::mlx_map_string_to_string_iterator_free(self.0);
301 }
302 }
303}