1use std::ffi::CString;
15
16use std::ptr::NonNull;
17use std::slice;
18use std::str;
19
20use crate::{sys, MaaError, MaaResult};
21
22macro_rules! impl_buffer_lifecycle {
24 ($name:ident, $sys_type:ty, $create_fn:path, $destroy_fn:path) => {
25 unsafe impl Send for $name {}
26
27 impl $name {
28 pub fn new() -> MaaResult<Self> {
30 let handle = unsafe { $create_fn() };
31 NonNull::new(handle)
32 .map(|ptr| Self {
33 handle: ptr,
34 own: true,
35 })
36 .ok_or(MaaError::NullPointer)
37 }
38
39 pub unsafe fn from_raw(handle: *mut $sys_type) -> Self {
47 Self {
48 handle: NonNull::new_unchecked(handle),
49 own: false,
50 }
51 }
52
53 pub fn from_handle(handle: *mut $sys_type) -> Option<Self> {
56 NonNull::new(handle).map(|ptr| Self {
57 handle: ptr,
58 own: false,
59 })
60 }
61
62 #[inline]
64 pub fn as_ptr(&self) -> *mut $sys_type {
65 self.handle.as_ptr()
66 }
67
68 #[inline]
70 pub fn raw(&self) -> *mut $sys_type {
71 self.handle.as_ptr()
72 }
73 }
74
75 impl Drop for $name {
76 fn drop(&mut self) {
77 if self.own {
78 unsafe { $destroy_fn(self.handle.as_ptr()) }
79 }
80 }
81 }
82
83 impl Default for $name {
84 fn default() -> Self {
85 Self::new().expect(concat!("Failed to create ", stringify!($name)))
86 }
87 }
88
89 impl std::fmt::Debug for $name {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 f.debug_struct(stringify!($name))
92 .field("handle", &self.handle)
93 .field("own", &self.own)
94 .finish()
95 }
96 }
97 };
98}
99
100pub struct MaaStringBuffer {
105 handle: NonNull<sys::MaaStringBuffer>,
106 own: bool,
107}
108
109impl_buffer_lifecycle!(
110 MaaStringBuffer,
111 sys::MaaStringBuffer,
112 sys::MaaStringBufferCreate,
113 sys::MaaStringBufferDestroy
114);
115
116impl MaaStringBuffer {
117 pub fn set<S: AsRef<str>>(&mut self, content: S) -> MaaResult<()> {
119 let s = content.as_ref();
120 let c_str = CString::new(s)?;
121 let ret = unsafe { sys::MaaStringBufferSet(self.handle.as_ptr(), c_str.as_ptr()) };
122 crate::common::check_bool(ret)
123 }
124
125 pub fn set_ex<B: AsRef<[u8]>>(&mut self, content: B) -> MaaResult<()> {
130 let bytes = content.as_ref();
131 let ret = unsafe {
132 sys::MaaStringBufferSetEx(
133 self.handle.as_ptr(),
134 bytes.as_ptr() as *const _,
135 bytes.len() as u64,
136 )
137 };
138 crate::common::check_bool(ret)
139 }
140
141 pub fn as_str(&self) -> &str {
143 let bytes = self.as_bytes();
144 if bytes.is_empty() {
145 ""
146 } else {
147 str::from_utf8(bytes).unwrap_or("")
148 }
149 }
150
151 pub fn as_bytes(&self) -> &[u8] {
153 unsafe {
154 let ptr = sys::MaaStringBufferGet(self.handle.as_ptr());
155 let size = sys::MaaStringBufferSize(self.handle.as_ptr()) as usize;
156
157 if ptr.is_null() || size == 0 {
158 &[]
159 } else {
160 slice::from_raw_parts(ptr as *const u8, size)
161 }
162 }
163 }
164
165 pub fn is_empty(&self) -> bool {
167 unsafe { sys::MaaStringBufferIsEmpty(self.handle.as_ptr()) != 0 }
168 }
169
170 pub fn clear(&mut self) -> MaaResult<()> {
172 let ret = unsafe { sys::MaaStringBufferClear(self.handle.as_ptr()) };
173 crate::common::check_bool(ret)
174 }
175
176 pub fn len(&self) -> usize {
178 unsafe { sys::MaaStringBufferSize(self.handle.as_ptr()) as usize }
179 }
180}
181
182impl std::fmt::Display for MaaStringBuffer {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 f.write_str(self.as_str())
185 }
186}
187
188impl From<&str> for MaaStringBuffer {
189 fn from(s: &str) -> Self {
190 let mut buf = Self::new().expect("Failed to create MaaStringBuffer");
191 buf.set(s).expect("Failed to set string buffer content");
192 buf
193 }
194}
195
196impl AsRef<str> for MaaStringBuffer {
197 fn as_ref(&self) -> &str {
198 self.as_str()
199 }
200}
201
202pub struct MaaImageBuffer {
207 handle: NonNull<sys::MaaImageBuffer>,
208 own: bool,
209}
210
211impl_buffer_lifecycle!(
212 MaaImageBuffer,
213 sys::MaaImageBuffer,
214 sys::MaaImageBufferCreate,
215 sys::MaaImageBufferDestroy
216);
217
218impl MaaImageBuffer {
219 pub fn is_empty(&self) -> bool {
221 unsafe { sys::MaaImageBufferIsEmpty(self.handle.as_ptr()) != 0 }
222 }
223
224 pub fn clear(&mut self) -> MaaResult<()> {
226 let ret = unsafe { sys::MaaImageBufferClear(self.handle.as_ptr()) };
227 crate::common::check_bool(ret)
228 }
229
230 pub fn width(&self) -> i32 {
232 unsafe { sys::MaaImageBufferWidth(self.handle.as_ptr()) }
233 }
234
235 pub fn height(&self) -> i32 {
237 unsafe { sys::MaaImageBufferHeight(self.handle.as_ptr()) }
238 }
239
240 pub fn channels(&self) -> i32 {
242 unsafe { sys::MaaImageBufferChannels(self.handle.as_ptr()) }
243 }
244
245 pub fn image_type(&self) -> i32 {
247 unsafe { sys::MaaImageBufferType(self.handle.as_ptr()) }
248 }
249
250 pub fn to_vec(&self) -> Option<Vec<u8>> {
252 unsafe {
253 let ptr = sys::MaaImageBufferGetEncoded(self.handle.as_ptr());
254 let size = sys::MaaImageBufferGetEncodedSize(self.handle.as_ptr());
255 if !ptr.is_null() && size > 0 {
256 let slice = slice::from_raw_parts(ptr, size as usize);
257 Some(slice.to_vec())
258 } else {
259 None
260 }
261 }
262 }
263
264 pub fn raw_data(&self) -> Option<&[u8]> {
266 unsafe {
267 let ptr = sys::MaaImageBufferGetRawData(self.handle.as_ptr());
268 if ptr.is_null() {
269 return None;
270 }
271 let w = self.width() as usize;
272 let h = self.height() as usize;
273 let c = self.channels() as usize;
274 if w == 0 || h == 0 || c == 0 {
275 return None;
276 }
277 Some(slice::from_raw_parts(ptr as *const u8, w * h * c))
278 }
279 }
280
281 pub fn set_raw_data(
283 &mut self,
284 data: &[u8],
285 width: i32,
286 height: i32,
287 img_type: i32,
288 ) -> MaaResult<()> {
289 let ret = unsafe {
290 sys::MaaImageBufferSetRawData(
291 self.handle.as_ptr(),
292 data.as_ptr() as *mut std::ffi::c_void,
293 width,
294 height,
295 img_type,
296 )
297 };
298 crate::common::check_bool(ret)
299 }
300
301 pub fn set(&mut self, data: &[u8], width: i32, height: i32) -> MaaResult<()> {
303 self.set_raw_data(data, width, height, 16)
304 }
305
306 pub fn set_encoded(&mut self, data: &[u8]) -> MaaResult<()> {
308 let ret = unsafe {
309 sys::MaaImageBufferSetEncoded(
310 self.handle.as_ptr(),
311 data.as_ptr() as *mut u8,
312 data.len() as u64,
313 )
314 };
315 crate::common::check_bool(ret)
316 }
317
318 pub fn resize(&mut self, width: i32, height: i32) -> MaaResult<()> {
323 let ret = unsafe { sys::MaaImageBufferResize(self.handle.as_ptr(), width, height) };
324 crate::common::check_bool(ret)
325 }
326
327 #[cfg(feature = "image")]
329 pub fn to_dynamic_image(&self) -> MaaResult<image::DynamicImage> {
330 let encoded = self.to_vec().ok_or(MaaError::ImageConversionError)?;
331 image::load_from_memory(&encoded).map_err(|_| MaaError::ImageConversionError)
332 }
333
334 #[cfg(feature = "image")]
336 pub fn from_dynamic_image(img: &image::DynamicImage) -> MaaResult<Self> {
337 use std::io::Cursor;
338
339 let mut bytes = Vec::new();
340 img.write_to(&mut Cursor::new(&mut bytes), image::ImageFormat::Png)
341 .map_err(|_| MaaError::ImageConversionError)?;
342
343 let mut buffer = Self::new()?;
344 buffer.set_encoded(&bytes)?;
345 Ok(buffer)
346 }
347
348 #[cfg(feature = "image")]
350 pub fn from_rgb_image(img: &image::RgbImage) -> MaaResult<Self> {
351 Self::from_dynamic_image(&image::DynamicImage::ImageRgb8(img.clone()))
352 }
353
354 #[cfg(feature = "image")]
356 pub fn from_rgba_image(img: &image::RgbaImage) -> MaaResult<Self> {
357 Self::from_dynamic_image(&image::DynamicImage::ImageRgba8(img.clone()))
358 }
359}
360
361pub struct MaaImageListBuffer {
365 handle: NonNull<sys::MaaImageListBuffer>,
366 own: bool,
367}
368
369impl_buffer_lifecycle!(
370 MaaImageListBuffer,
371 sys::MaaImageListBuffer,
372 sys::MaaImageListBufferCreate,
373 sys::MaaImageListBufferDestroy
374);
375
376impl MaaImageListBuffer {
377 pub fn len(&self) -> usize {
379 unsafe { sys::MaaImageListBufferSize(self.handle.as_ptr()) as usize }
380 }
381
382 pub fn is_empty(&self) -> bool {
384 unsafe { sys::MaaImageListBufferIsEmpty(self.handle.as_ptr()) != 0 }
385 }
386
387 pub fn at(&self, index: usize) -> Option<MaaImageBuffer> {
390 unsafe {
391 let ptr = sys::MaaImageListBufferAt(self.handle.as_ptr(), index as u64);
392 MaaImageBuffer::from_handle(ptr as *mut sys::MaaImageBuffer)
393 }
394 }
395
396 pub fn append(&self, image: &MaaImageBuffer) -> MaaResult<()> {
398 let ret = unsafe { sys::MaaImageListBufferAppend(self.handle.as_ptr(), image.as_ptr()) };
399 crate::common::check_bool(ret)
400 }
401
402 pub fn set(&self, data: &[&MaaImageBuffer]) -> MaaResult<()> {
404 self.clear()?;
405 for img in data {
406 self.append(img)?;
407 }
408 Ok(())
409 }
410
411 pub fn remove(&self, index: usize) -> MaaResult<()> {
413 let ret = unsafe { sys::MaaImageListBufferRemove(self.handle.as_ptr(), index as u64) };
414 crate::common::check_bool(ret)
415 }
416
417 pub fn clear(&self) -> MaaResult<()> {
419 let ret = unsafe { sys::MaaImageListBufferClear(self.handle.as_ptr()) };
420 crate::common::check_bool(ret)
421 }
422
423 pub fn to_vec(&self) -> Vec<MaaImageBuffer> {
425 (0..self.len()).filter_map(|i| self.at(i)).collect()
426 }
427
428 pub fn iter(&self) -> impl Iterator<Item = MaaImageBuffer> + '_ {
430 (0..self.len()).filter_map(move |i| self.at(i))
431 }
432
433 pub fn to_vec_of_vec(&self) -> Vec<Vec<u8>> {
435 self.iter().filter_map(|img| img.to_vec()).collect()
436 }
437
438 pub fn to_raw_vecs(&self) -> Vec<(Vec<u8>, i32, i32, i32, i32)> {
440 self.iter()
441 .filter_map(|img| {
442 img.raw_data().map(|data| {
443 (
444 data.to_vec(),
445 img.width(),
446 img.height(),
447 img.channels(),
448 img.image_type(),
449 )
450 })
451 })
452 .collect()
453 }
454}
455
456pub struct MaaStringListBuffer {
460 handle: NonNull<sys::MaaStringListBuffer>,
461 own: bool,
462}
463
464impl_buffer_lifecycle!(
465 MaaStringListBuffer,
466 sys::MaaStringListBuffer,
467 sys::MaaStringListBufferCreate,
468 sys::MaaStringListBufferDestroy
469);
470
471impl MaaStringListBuffer {
472 pub fn len(&self) -> usize {
474 unsafe { sys::MaaStringListBufferSize(self.handle.as_ptr()) as usize }
475 }
476
477 pub fn is_empty(&self) -> bool {
479 unsafe { sys::MaaStringListBufferIsEmpty(self.handle.as_ptr()) != 0 }
480 }
481
482 pub fn append(&self, s: &str) -> MaaResult<()> {
484 let mut str_buf = MaaStringBuffer::new()?;
485 str_buf.set(s)?;
486 let ret = unsafe { sys::MaaStringListBufferAppend(self.handle.as_ptr(), str_buf.as_ptr()) };
487 crate::common::check_bool(ret)
488 }
489
490 pub fn set<S: AsRef<str>>(&self, data: &[S]) -> MaaResult<()> {
492 self.clear()?;
493 for s in data {
494 self.append(s.as_ref())?;
495 }
496 Ok(())
497 }
498
499 pub fn remove(&self, index: usize) -> MaaResult<()> {
501 let ret = unsafe { sys::MaaStringListBufferRemove(self.handle.as_ptr(), index as u64) };
502 crate::common::check_bool(ret)
503 }
504
505 pub fn clear(&self) -> MaaResult<()> {
507 let ret = unsafe { sys::MaaStringListBufferClear(self.handle.as_ptr()) };
508 crate::common::check_bool(ret)
509 }
510
511 pub fn iter(&self) -> impl Iterator<Item = &str> + '_ {
516 (0..self.len()).map(move |i| unsafe {
517 let ptr = sys::MaaStringListBufferAt(self.handle.as_ptr(), i as u64);
518 if ptr.is_null() {
520 return "";
521 }
522 let str_ptr = sys::MaaStringBufferGet(ptr as *mut sys::MaaStringBuffer);
523 let size = sys::MaaStringBufferSize(ptr as *mut sys::MaaStringBuffer) as usize;
524 if str_ptr.is_null() || size == 0 {
525 ""
526 } else {
527 let slice = slice::from_raw_parts(str_ptr as *const u8, size);
528 str::from_utf8(slice).unwrap_or("")
529 }
530 })
531 }
532
533 pub fn to_vec(&self) -> Vec<String> {
535 self.iter().map(|s| s.to_string()).collect()
536 }
537}
538
539pub struct MaaRectBuffer {
543 handle: NonNull<sys::MaaRect>,
544 own: bool,
545}
546
547impl_buffer_lifecycle!(
548 MaaRectBuffer,
549 sys::MaaRect,
550 sys::MaaRectCreate,
551 sys::MaaRectDestroy
552);
553
554impl MaaRectBuffer {
555 pub fn get(&self) -> crate::common::Rect {
557 unsafe {
558 crate::common::Rect {
559 x: sys::MaaRectGetX(self.handle.as_ptr()),
560 y: sys::MaaRectGetY(self.handle.as_ptr()),
561 width: sys::MaaRectGetW(self.handle.as_ptr()),
562 height: sys::MaaRectGetH(self.handle.as_ptr()),
563 }
564 }
565 }
566
567 pub fn set(&mut self, rect: &crate::common::Rect) -> MaaResult<()> {
569 let ret = unsafe {
570 sys::MaaRectSet(
571 self.handle.as_ptr(),
572 rect.x,
573 rect.y,
574 rect.width,
575 rect.height,
576 )
577 };
578 crate::common::check_bool(ret)
579 }
580}
581
582impl From<crate::common::Rect> for MaaRectBuffer {
583 fn from(rect: crate::common::Rect) -> Self {
584 let mut buf = Self::new().expect("Failed to create MaaRectBuffer");
585 buf.set(&rect).expect("Failed to set rect buffer");
586 buf
587 }
588}
589
590impl From<MaaRectBuffer> for crate::common::Rect {
591 fn from(buf: MaaRectBuffer) -> Self {
592 buf.get()
593 }
594}
595
596impl From<&MaaRectBuffer> for crate::common::Rect {
597 fn from(buf: &MaaRectBuffer) -> Self {
598 buf.get()
599 }
600}