1use std::ffi::CString;
4use std::ptr::NonNull;
5
6use crate::{MaaError, MaaResult, common, sys};
7
8use std::sync::Arc;
16
17struct ResourceInner {
18 handle: NonNull<sys::MaaResource>,
19 owns_handle: bool,
20 custom_actions: std::sync::Mutex<std::collections::HashMap<String, usize>>, custom_recognitions: std::sync::Mutex<std::collections::HashMap<String, usize>>,
22 callbacks: std::sync::Mutex<std::collections::HashMap<sys::MaaSinkId, usize>>,
23 event_sinks: std::sync::Mutex<std::collections::HashMap<sys::MaaSinkId, usize>>,
24}
25
26unsafe impl Send for ResourceInner {}
27unsafe impl Sync for ResourceInner {}
28
29#[derive(Clone)]
30pub struct Resource {
31 inner: Arc<ResourceInner>,
32}
33
34unsafe impl Send for Resource {}
35unsafe impl Sync for Resource {}
36
37impl Resource {
38 pub fn new() -> MaaResult<Self> {
40 let handle = unsafe { sys::MaaResourceCreate() };
41 if let Some(ptr) = NonNull::new(handle) {
42 Ok(Self {
43 inner: Arc::new(ResourceInner {
44 handle: ptr,
45 owns_handle: true,
46 custom_actions: std::sync::Mutex::new(std::collections::HashMap::new()),
47 custom_recognitions: std::sync::Mutex::new(std::collections::HashMap::new()),
48 callbacks: std::sync::Mutex::new(std::collections::HashMap::new()),
49 event_sinks: std::sync::Mutex::new(std::collections::HashMap::new()),
50 }),
51 })
52 } else {
53 Err(MaaError::NullPointer)
54 }
55 }
56
57 pub unsafe fn from_raw(ptr: *mut sys::MaaResource) -> MaaResult<Self> {
63 if let Some(handle) = NonNull::new(ptr) {
64 Ok(Self {
65 inner: Arc::new(ResourceInner {
66 handle,
67 owns_handle: true,
68 custom_actions: std::sync::Mutex::new(std::collections::HashMap::new()),
69 custom_recognitions: std::sync::Mutex::new(std::collections::HashMap::new()),
70 callbacks: std::sync::Mutex::new(std::collections::HashMap::new()),
71 event_sinks: std::sync::Mutex::new(std::collections::HashMap::new()),
72 }),
73 })
74 } else {
75 Err(MaaError::NullPointer)
76 }
77 }
78
79 pub fn post_bundle(&self, path: &str) -> MaaResult<crate::job::ResJob> {
83 let c_path = CString::new(path)?;
84 let id = unsafe { sys::MaaResourcePostBundle(self.inner.handle.as_ptr(), c_path.as_ptr()) };
85 Ok(crate::job::Job::for_resource(self, id))
86 }
87
88 pub fn loaded(&self) -> bool {
90 unsafe { sys::MaaResourceLoaded(self.inner.handle.as_ptr()) != 0 }
91 }
92
93 pub fn clear(&self) -> MaaResult<()> {
95 let ret = unsafe { sys::MaaResourceClear(self.inner.handle.as_ptr()) };
96 common::check_bool(ret)
97 }
98
99 pub fn status(&self, id: common::MaaId) -> common::MaaStatus {
101 let status = unsafe { sys::MaaResourceStatus(self.inner.handle.as_ptr(), id) };
102 common::MaaStatus(status)
103 }
104
105 pub fn wait(&self, id: common::MaaId) -> common::MaaStatus {
107 let status = unsafe { sys::MaaResourceWait(self.inner.handle.as_ptr(), id) };
108 common::MaaStatus(status)
109 }
110
111 pub fn raw(&self) -> *mut sys::MaaResource {
113 self.inner.handle.as_ptr()
114 }
115
116 pub fn post_ocr_model(&self, path: &str) -> MaaResult<crate::job::ResJob> {
120 let c_path = CString::new(path)?;
121 let id =
122 unsafe { sys::MaaResourcePostOcrModel(self.inner.handle.as_ptr(), c_path.as_ptr()) };
123 Ok(crate::job::Job::for_resource(self, id))
124 }
125
126 pub fn post_pipeline(&self, path: &str) -> MaaResult<crate::job::ResJob> {
128 let c_path = CString::new(path)?;
129 let id =
130 unsafe { sys::MaaResourcePostPipeline(self.inner.handle.as_ptr(), c_path.as_ptr()) };
131 Ok(crate::job::Job::for_resource(self, id))
132 }
133
134 pub fn post_image(&self, path: &str) -> MaaResult<crate::job::ResJob> {
136 let c_path = CString::new(path)?;
137 let id = unsafe { sys::MaaResourcePostImage(self.inner.handle.as_ptr(), c_path.as_ptr()) };
138 Ok(crate::job::Job::for_resource(self, id))
139 }
140
141 pub fn override_pipeline(&self, pipeline_override: &str) -> MaaResult<()> {
145 let c_json = CString::new(pipeline_override)?;
146 let ret = unsafe {
147 sys::MaaResourceOverridePipeline(self.inner.handle.as_ptr(), c_json.as_ptr())
148 };
149 common::check_bool(ret)
150 }
151
152 pub fn override_pipeline_json(&self, pipeline_override: &serde_json::Value) -> MaaResult<()> {
164 self.override_pipeline(&pipeline_override.to_string())
165 }
166
167 pub fn override_next(&self, node_name: &str, next_list: &[&str]) -> MaaResult<()> {
173 let c_name = CString::new(node_name)?;
174 let list_buf = crate::buffer::MaaStringListBuffer::new()?;
175 for item in next_list {
176 list_buf.append(item)?;
177 }
178 let ret = unsafe {
179 sys::MaaResourceOverrideNext(
180 self.inner.handle.as_ptr(),
181 c_name.as_ptr(),
182 list_buf.raw(),
183 )
184 };
185 common::check_bool(ret)
186 }
187
188 pub fn get_node_data(&self, node_name: &str) -> MaaResult<Option<String>> {
190 let c_name = CString::new(node_name)?;
191 let buffer = crate::buffer::MaaStringBuffer::new()?;
192 let ret = unsafe {
193 sys::MaaResourceGetNodeData(self.inner.handle.as_ptr(), c_name.as_ptr(), buffer.raw())
194 };
195 if ret != 0 {
196 Ok(Some(buffer.to_string()))
197 } else {
198 Ok(None)
199 }
200 }
201
202 pub fn get_node_object(
204 &self,
205 node_name: &str,
206 ) -> MaaResult<Option<crate::pipeline::PipelineData>> {
207 if let Some(json_str) = self.get_node_data(node_name)? {
208 let data: crate::pipeline::PipelineData =
209 serde_json::from_str(&json_str).map_err(|e| {
210 MaaError::InvalidConfig(format!("Failed to parse pipeline data: {}", e))
211 })?;
212 Ok(Some(data))
213 } else {
214 Ok(None)
215 }
216 }
217
218 pub fn node_list(&self) -> MaaResult<Vec<String>> {
220 let buffer = crate::buffer::MaaStringListBuffer::new()?;
221 let ret = unsafe { sys::MaaResourceGetNodeList(self.inner.handle.as_ptr(), buffer.raw()) };
222 if ret != 0 {
223 Ok(buffer.to_vec())
224 } else {
225 Err(MaaError::FrameworkError(0))
226 }
227 }
228
229 pub fn hash(&self) -> MaaResult<String> {
231 let buffer = crate::buffer::MaaStringBuffer::new()?;
232 let ret = unsafe { sys::MaaResourceGetHash(self.inner.handle.as_ptr(), buffer.raw()) };
233 if ret != 0 {
234 Ok(buffer.to_string())
235 } else {
236 Err(MaaError::FrameworkError(0))
237 }
238 }
239
240 pub fn get_default_recognition_param(
245 &self,
246 reco_type: &str,
247 ) -> MaaResult<Option<serde_json::Value>> {
248 let c_type = CString::new(reco_type)?;
249 let buffer = crate::buffer::MaaStringBuffer::new()?;
250 let ret = unsafe {
251 sys::MaaResourceGetDefaultRecognitionParam(
252 self.inner.handle.as_ptr(),
253 c_type.as_ptr(),
254 buffer.raw(),
255 )
256 };
257 if ret != 0 {
258 let json_str = buffer.to_string();
259 let val: serde_json::Value = serde_json::from_str(&json_str).map_err(|e| {
260 MaaError::InvalidConfig(format!("Failed to parse default params: {}", e))
261 })?;
262 Ok(Some(val))
263 } else {
264 Ok(None)
265 }
266 }
267
268 pub fn get_default_action_param(
273 &self,
274 action_type: &str,
275 ) -> MaaResult<Option<serde_json::Value>> {
276 let c_type = CString::new(action_type)?;
277 let buffer = crate::buffer::MaaStringBuffer::new()?;
278 let ret = unsafe {
279 sys::MaaResourceGetDefaultActionParam(
280 self.inner.handle.as_ptr(),
281 c_type.as_ptr(),
282 buffer.raw(),
283 )
284 };
285 if ret != 0 {
286 let json_str = buffer.to_string();
287 let val: serde_json::Value = serde_json::from_str(&json_str).map_err(|e| {
288 MaaError::InvalidConfig(format!("Failed to parse default params: {}", e))
289 })?;
290 Ok(Some(val))
291 } else {
292 Ok(None)
293 }
294 }
295
296 pub fn use_cpu(&self) -> MaaResult<()> {
300 let mut ep: i32 =
301 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_CPU as i32;
302 let ret1 = unsafe {
303 sys::MaaResourceSetOption(
304 self.inner.handle.as_ptr(),
305 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
306 &mut ep as *mut _ as *mut std::ffi::c_void,
307 std::mem::size_of::<i32>() as u64,
308 )
309 };
310 common::check_bool(ret1)?;
311
312 let mut device: i32 = sys::MaaInferenceDeviceEnum_MaaInferenceDevice_CPU as i32;
313 let ret2 = unsafe {
314 sys::MaaResourceSetOption(
315 self.inner.handle.as_ptr(),
316 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
317 &mut device as *mut _ as *mut std::ffi::c_void,
318 std::mem::size_of::<i32>() as u64,
319 )
320 };
321 common::check_bool(ret2)
322 }
323
324 pub fn use_directml(&self, device_id: i32) -> MaaResult<()> {
329 let mut ep: i32 =
330 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_DirectML as i32;
331 let ret1 = unsafe {
332 sys::MaaResourceSetOption(
333 self.inner.handle.as_ptr(),
334 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
335 &mut ep as *mut _ as *mut std::ffi::c_void,
336 std::mem::size_of::<i32>() as u64,
337 )
338 };
339 common::check_bool(ret1)?;
340
341 let mut device = device_id;
342 let ret2 = unsafe {
343 sys::MaaResourceSetOption(
344 self.inner.handle.as_ptr(),
345 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
346 &mut device as *mut _ as *mut std::ffi::c_void,
347 std::mem::size_of::<i32>() as u64,
348 )
349 };
350 common::check_bool(ret2)
351 }
352
353 pub fn use_webgpu(&self, device_id: i32) -> MaaResult<()> {
358 let mut ep: i32 =
359 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_WebGPU as i32;
360 let ret1 = unsafe {
361 sys::MaaResourceSetOption(
362 self.inner.handle.as_ptr(),
363 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
364 &mut ep as *mut _ as *mut std::ffi::c_void,
365 std::mem::size_of::<i32>() as u64,
366 )
367 };
368 common::check_bool(ret1)?;
369
370 let mut device = device_id;
371 let ret2 = unsafe {
372 sys::MaaResourceSetOption(
373 self.inner.handle.as_ptr(),
374 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
375 &mut device as *mut _ as *mut std::ffi::c_void,
376 std::mem::size_of::<i32>() as u64,
377 )
378 };
379 common::check_bool(ret2)
380 }
381
382 pub fn use_ncnn(&self) -> MaaResult<()> {
389 let mut ep: i32 =
390 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_NCNN as i32;
391 let ret1 = unsafe {
392 sys::MaaResourceSetOption(
393 self.inner.handle.as_ptr(),
394 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
395 &mut ep as *mut _ as *mut std::ffi::c_void,
396 std::mem::size_of::<i32>() as u64,
397 )
398 };
399 common::check_bool(ret1)?;
400
401 let mut device: i32 = sys::MaaInferenceDeviceEnum_MaaInferenceDevice_CPU as i32;
402 let ret2 = unsafe {
403 sys::MaaResourceSetOption(
404 self.inner.handle.as_ptr(),
405 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
406 &mut device as *mut _ as *mut std::ffi::c_void,
407 std::mem::size_of::<i32>() as u64,
408 )
409 };
410 common::check_bool(ret2)
411 }
412
413 pub fn add_sink<F>(&self, callback: F) -> MaaResult<sys::MaaSinkId>
419 where
420 F: Fn(&str, &str) + Send + Sync + 'static,
421 {
422 let (cb_fn, cb_arg) = crate::callback::EventCallback::new(callback);
423 let sink_id = unsafe { sys::MaaResourceAddSink(self.inner.handle.as_ptr(), cb_fn, cb_arg) };
424 if sink_id != 0 {
425 self.inner
426 .callbacks
427 .lock()
428 .unwrap()
429 .insert(sink_id, cb_arg as usize);
430 Ok(sink_id)
431 } else {
432 unsafe { crate::callback::EventCallback::drop_callback(cb_arg) };
433 Err(MaaError::FrameworkError(0))
434 }
435 }
436
437 pub fn add_event_sink(
449 &self,
450 sink: Box<dyn crate::event_sink::EventSink>,
451 ) -> MaaResult<sys::MaaSinkId> {
452 let handle_id = self.inner.handle.as_ptr() as crate::common::MaaId;
453 let (cb, arg) = crate::callback::EventCallback::new_sink(handle_id, sink);
454 let id = unsafe { sys::MaaResourceAddSink(self.inner.handle.as_ptr(), cb, arg) };
455 if id > 0 {
456 self.inner
457 .event_sinks
458 .lock()
459 .unwrap()
460 .insert(id, arg as usize);
461 Ok(id)
462 } else {
463 unsafe { crate::callback::EventCallback::drop_sink(arg) };
464 Err(MaaError::FrameworkError(0))
465 }
466 }
467
468 pub fn remove_sink(&self, sink_id: sys::MaaSinkId) {
470 unsafe { sys::MaaResourceRemoveSink(self.inner.handle.as_ptr(), sink_id) }
471 if let Some(ptr) = self.inner.callbacks.lock().unwrap().remove(&sink_id) {
472 unsafe { crate::callback::EventCallback::drop_callback(ptr as *mut std::ffi::c_void) };
473 } else if let Some(ptr) = self.inner.event_sinks.lock().unwrap().remove(&sink_id) {
474 unsafe { crate::callback::EventCallback::drop_sink(ptr as *mut std::ffi::c_void) };
475 }
476 }
477
478 pub fn clear_sinks(&self) {
480 unsafe { sys::MaaResourceClearSinks(self.inner.handle.as_ptr()) }
481 let mut callbacks = self.inner.callbacks.lock().unwrap();
482 for (_, ptr) in callbacks.drain() {
483 unsafe { crate::callback::EventCallback::drop_callback(ptr as *mut std::ffi::c_void) };
484 }
485 let mut event_sinks = self.inner.event_sinks.lock().unwrap();
486 for (_, ptr) in event_sinks.drain() {
487 unsafe { crate::callback::EventCallback::drop_sink(ptr as *mut std::ffi::c_void) };
488 }
489 }
490
491 pub fn override_image(
499 &self,
500 image_name: &str,
501 image: &crate::buffer::MaaImageBuffer,
502 ) -> MaaResult<()> {
503 let c_name = CString::new(image_name)?;
504 let ret = unsafe {
505 sys::MaaResourceOverrideImage(self.inner.handle.as_ptr(), c_name.as_ptr(), image.raw())
506 };
507 common::check_bool(ret)
508 }
509
510 pub fn use_auto_ep(&self) -> MaaResult<()> {
516 let mut ep: i32 =
517 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_Auto as i32;
518 let ret1 = unsafe {
519 sys::MaaResourceSetOption(
520 self.inner.handle.as_ptr(),
521 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
522 &mut ep as *mut _ as *mut std::ffi::c_void,
523 std::mem::size_of::<i32>() as u64,
524 )
525 };
526 common::check_bool(ret1)?;
527
528 let mut device: i32 = sys::MaaInferenceDeviceEnum_MaaInferenceDevice_Auto as i32;
529 let ret2 = unsafe {
530 sys::MaaResourceSetOption(
531 self.inner.handle.as_ptr(),
532 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
533 &mut device as *mut _ as *mut std::ffi::c_void,
534 std::mem::size_of::<i32>() as u64,
535 )
536 };
537 common::check_bool(ret2)
538 }
539
540 #[deprecated(note = "MaaDeps no longer ships CoreML; use `use_webgpu` instead")]
547 pub fn use_coreml(&self, coreml_flag: i32) -> MaaResult<()> {
548 let mut ep: i32 =
549 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_CoreML as i32;
550 let ret1 = unsafe {
551 sys::MaaResourceSetOption(
552 self.inner.handle.as_ptr(),
553 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
554 &mut ep as *mut _ as *mut std::ffi::c_void,
555 std::mem::size_of::<i32>() as u64,
556 )
557 };
558 common::check_bool(ret1)?;
559
560 let mut device = coreml_flag;
561 let ret2 = unsafe {
562 sys::MaaResourceSetOption(
563 self.inner.handle.as_ptr(),
564 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
565 &mut device as *mut _ as *mut std::ffi::c_void,
566 std::mem::size_of::<i32>() as u64,
567 )
568 };
569 common::check_bool(ret2)
570 }
571
572 pub fn use_cuda(&self, nvidia_gpu_id: i32) -> MaaResult<()> {
577 let mut ep: i32 =
578 sys::MaaInferenceExecutionProviderEnum_MaaInferenceExecutionProvider_CUDA as i32;
579 let ret1 = unsafe {
580 sys::MaaResourceSetOption(
581 self.inner.handle.as_ptr(),
582 sys::MaaResOptionEnum_MaaResOption_InferenceExecutionProvider as i32,
583 &mut ep as *mut _ as *mut std::ffi::c_void,
584 std::mem::size_of::<i32>() as u64,
585 )
586 };
587 common::check_bool(ret1)?;
588
589 let mut device = nvidia_gpu_id;
590 let ret2 = unsafe {
591 sys::MaaResourceSetOption(
592 self.inner.handle.as_ptr(),
593 sys::MaaResOptionEnum_MaaResOption_InferenceDevice as i32,
594 &mut device as *mut _ as *mut std::ffi::c_void,
595 std::mem::size_of::<i32>() as u64,
596 )
597 };
598 common::check_bool(ret2)
599 }
600
601 pub fn unregister_custom_recognition(&self, name: &str) -> MaaResult<()> {
605 let c_name = CString::new(name)?;
606 let ret = unsafe {
607 sys::MaaResourceUnregisterCustomRecognition(self.inner.handle.as_ptr(), c_name.as_ptr())
608 };
609 if ret != 0 {
610 self.inner.custom_recognitions.lock().unwrap().remove(name);
611 }
612 common::check_bool(ret)
613 }
614
615 pub fn unregister_custom_action(&self, name: &str) -> MaaResult<()> {
617 let c_name = CString::new(name)?;
618 let ret = unsafe {
619 sys::MaaResourceUnregisterCustomAction(self.inner.handle.as_ptr(), c_name.as_ptr())
620 };
621 if ret != 0 {
622 self.inner.custom_actions.lock().unwrap().remove(name);
623 }
624 common::check_bool(ret)
625 }
626
627 pub fn custom_recognition_list(&self) -> MaaResult<Vec<String>> {
629 let buffer = crate::buffer::MaaStringListBuffer::new()?;
630 let ret = unsafe {
631 sys::MaaResourceGetCustomRecognitionList(self.inner.handle.as_ptr(), buffer.raw())
632 };
633 if ret != 0 {
634 Ok(buffer.to_vec())
635 } else {
636 Err(MaaError::FrameworkError(0))
637 }
638 }
639
640 pub fn custom_action_list(&self) -> MaaResult<Vec<String>> {
642 let buffer = crate::buffer::MaaStringListBuffer::new()?;
643 let ret = unsafe {
644 sys::MaaResourceGetCustomActionList(self.inner.handle.as_ptr(), buffer.raw())
645 };
646 if ret != 0 {
647 Ok(buffer.to_vec())
648 } else {
649 Err(MaaError::FrameworkError(0))
650 }
651 }
652
653 pub fn clear_custom_recognition(&self) -> MaaResult<()> {
655 let ret = unsafe { sys::MaaResourceClearCustomRecognition(self.inner.handle.as_ptr()) };
656 if ret != 0 {
657 let mut recos = self.inner.custom_recognitions.lock().unwrap();
658 for (_, ptr) in recos.drain() {
659 unsafe {
660 let _ = Box::from_raw(ptr as *mut Box<dyn crate::custom::CustomRecognition>);
661 }
662 }
663 }
664 common::check_bool(ret)
665 }
666
667 pub fn clear_custom_action(&self) -> MaaResult<()> {
669 let ret = unsafe { sys::MaaResourceClearCustomAction(self.inner.handle.as_ptr()) };
670 if ret != 0 {
671 let mut actions = self.inner.custom_actions.lock().unwrap();
672 for (_, ptr) in actions.drain() {
673 unsafe {
674 let _ = Box::from_raw(ptr as *mut Box<dyn crate::custom::CustomAction>);
675 }
676 }
677 }
678 common::check_bool(ret)
679 }
680 pub(crate) fn custom_recognitions(
681 &self,
682 ) -> &std::sync::Mutex<std::collections::HashMap<String, usize>> {
683 &self.inner.custom_recognitions
684 }
685
686 pub(crate) fn custom_actions(
687 &self,
688 ) -> &std::sync::Mutex<std::collections::HashMap<String, usize>> {
689 &self.inner.custom_actions
690 }
691}
692
693impl Drop for ResourceInner {
694 fn drop(&mut self) {
695 unsafe {
696 if self.owns_handle {
697 sys::MaaResourceClearSinks(self.handle.as_ptr());
698 {
699 let mut callbacks = self.callbacks.lock().unwrap();
700 for (_, ptr) in callbacks.drain() {
701 let _ = crate::callback::EventCallback::drop_callback(
702 ptr as *mut std::ffi::c_void,
703 );
704 }
705 }
706 {
707 let mut event_sinks = self.event_sinks.lock().unwrap();
708 for (_, ptr) in event_sinks.drain() {
709 let _ =
710 crate::callback::EventCallback::drop_sink(ptr as *mut std::ffi::c_void);
711 }
712 }
713
714 sys::MaaResourceClearCustomAction(self.handle.as_ptr());
715 sys::MaaResourceClearCustomRecognition(self.handle.as_ptr());
716
717 {
718 let mut actions = self.custom_actions.lock().unwrap();
719 for (_, ptr) in actions.drain() {
720 let _ = Box::from_raw(ptr as *mut Box<dyn crate::custom::CustomAction>);
721 }
722 }
723 {
724 let mut recos = self.custom_recognitions.lock().unwrap();
725 for (_, ptr) in recos.drain() {
726 let _ =
727 Box::from_raw(ptr as *mut Box<dyn crate::custom::CustomRecognition>);
728 }
729 }
730
731 sys::MaaResourceDestroy(self.handle.as_ptr());
732 }
733 }
734 }
735}
736
737pub struct ResourceRef<'a> {
745 handle: *mut sys::MaaResource,
746 _marker: std::marker::PhantomData<&'a ()>,
747}
748
749impl<'a> ResourceRef<'a> {
750 pub(crate) fn from_ptr(handle: *mut sys::MaaResource) -> Option<Self> {
751 if handle.is_null() {
752 None
753 } else {
754 Some(Self {
755 handle,
756 _marker: std::marker::PhantomData,
757 })
758 }
759 }
760
761 pub fn loaded(&self) -> bool {
763 unsafe { sys::MaaResourceLoaded(self.handle) != 0 }
764 }
765
766 pub fn status(&self, id: common::MaaId) -> common::MaaStatus {
768 let status = unsafe { sys::MaaResourceStatus(self.handle, id) };
769 common::MaaStatus(status)
770 }
771
772 pub fn wait(&self, id: common::MaaId) -> common::MaaStatus {
774 let status = unsafe { sys::MaaResourceWait(self.handle, id) };
775 common::MaaStatus(status)
776 }
777
778 pub fn hash(&self) -> MaaResult<String> {
780 let buffer = crate::buffer::MaaStringBuffer::new()?;
781 let ret = unsafe { sys::MaaResourceGetHash(self.handle, buffer.raw()) };
782 if ret != 0 {
783 Ok(buffer.to_string())
784 } else {
785 Err(MaaError::FrameworkError(0))
786 }
787 }
788
789 pub fn get_default_recognition_param(
791 &self,
792 reco_type: &str,
793 ) -> MaaResult<Option<serde_json::Value>> {
794 let c_type = std::ffi::CString::new(reco_type)?;
795 let buffer = crate::buffer::MaaStringBuffer::new()?;
796 let ret = unsafe {
797 sys::MaaResourceGetDefaultRecognitionParam(self.handle, c_type.as_ptr(), buffer.raw())
798 };
799 if ret != 0 {
800 let json_str = buffer.to_string();
801 let val: serde_json::Value = serde_json::from_str(&json_str).map_err(|e| {
802 MaaError::InvalidConfig(format!("Failed to parse default params: {}", e))
803 })?;
804 Ok(Some(val))
805 } else {
806 Ok(None)
807 }
808 }
809
810 pub fn get_default_action_param(
812 &self,
813 action_type: &str,
814 ) -> MaaResult<Option<serde_json::Value>> {
815 let c_type = std::ffi::CString::new(action_type)?;
816 let buffer = crate::buffer::MaaStringBuffer::new()?;
817 let ret = unsafe {
818 sys::MaaResourceGetDefaultActionParam(self.handle, c_type.as_ptr(), buffer.raw())
819 };
820 if ret != 0 {
821 let json_str = buffer.to_string();
822 let val: serde_json::Value = serde_json::from_str(&json_str).map_err(|e| {
823 MaaError::InvalidConfig(format!("Failed to parse default params: {}", e))
824 })?;
825 Ok(Some(val))
826 } else {
827 Ok(None)
828 }
829 }
830
831 pub fn node_list(&self) -> MaaResult<Vec<String>> {
833 let buffer = crate::buffer::MaaStringListBuffer::new()?;
834 let ret = unsafe { sys::MaaResourceGetNodeList(self.handle, buffer.raw()) };
835 if ret != 0 {
836 Ok(buffer.to_vec())
837 } else {
838 Err(MaaError::FrameworkError(0))
839 }
840 }
841
842 pub fn get_node_data(&self, node_name: &str) -> MaaResult<Option<String>> {
844 let c_name = std::ffi::CString::new(node_name)?;
845 let buffer = crate::buffer::MaaStringBuffer::new()?;
846 let ret =
847 unsafe { sys::MaaResourceGetNodeData(self.handle, c_name.as_ptr(), buffer.raw()) };
848 if ret != 0 {
849 Ok(Some(buffer.to_string()))
850 } else {
851 Ok(None)
852 }
853 }
854
855 pub fn raw(&self) -> *mut sys::MaaResource {
857 self.handle
858 }
859}