1use std::num::{
2 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
3 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
4};
5use std::ptr::NonNull;
6
7#[derive(Debug)]
9pub struct ScriptModuleCallHandle {
10 pub(crate) internal: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
11}
12
13#[derive(thiserror::Error, Debug)]
15pub enum ScriptModuleCallHandleError {
16 #[error("key contains null byte")]
17 KeyContainsNullByte(std::ffi::NulError),
18
19 #[error("value contains null byte")]
20 ValueContainsNullByte(std::ffi::NulError),
21
22 #[error("too many elements")]
23 TooManyElements,
24}
25
26pub type ScriptModuleCallHandleResult<T> = std::result::Result<T, ScriptModuleCallHandleError>;
27
28impl ScriptModuleCallHandle {
29 pub unsafe fn from_raw(
35 ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
36 ) -> ScriptModuleCallHandle {
37 ScriptModuleCallHandle { internal: ptr }
38 }
39
40 pub fn len(&self) -> usize {
42 unsafe { ((*self.internal).get_param_num)() as usize }
43 }
44
45 pub fn is_empty(&self) -> bool {
47 self.len() == 0
48 }
49
50 pub fn get_param<'a, T: FromScriptModuleParam<'a>>(&'a self, index: usize) -> Option<T> {
52 T::from_param(self, index)
53 }
54
55 pub fn get_param_int(&self, index: usize) -> i32 {
61 unsafe { ((*self.internal).get_param_int)(index as i32) }
62 }
63
64 pub fn get_param_float(&self, index: usize) -> f64 {
70 unsafe { ((*self.internal).get_param_double)(index as i32) }
71 }
72
73 pub fn get_param_str(&self, index: usize) -> Option<String> {
75 unsafe {
76 let c_str = ((*self.internal).get_param_string)(index as i32);
77 if c_str.is_null() {
78 None
79 } else {
80 Some(
81 std::ffi::CStr::from_ptr(c_str)
82 .to_string_lossy()
83 .into_owned(),
84 )
85 }
86 }
87 }
88
89 pub fn get_param_data<T>(&self, index: usize) -> Option<NonNull<T>> {
95 unsafe {
96 let data_ptr = ((*self.internal).get_param_data)(index as i32);
97 NonNull::new(data_ptr as *mut T)
98 }
99 }
100
101 pub fn get_param_boolean(&self, index: usize) -> bool {
107 unsafe { ((*self.internal).get_param_boolean)(index as i32) }
108 }
109
110 pub fn get_param_table_int(
116 &self,
117 index: usize,
118 key: &str,
119 ) -> ScriptModuleCallHandleResult<i32> {
120 let c_key = std::ffi::CString::new(key)
121 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
122 Ok(unsafe { ((*self.internal).get_param_table_int)(index as i32, c_key.as_ptr()) })
123 }
124
125 pub fn get_param_table_float(
131 &self,
132 index: usize,
133 key: &str,
134 ) -> ScriptModuleCallHandleResult<f64> {
135 let c_key = std::ffi::CString::new(key)
136 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
137 Ok(unsafe { ((*self.internal).get_param_table_double)(index as i32, c_key.as_ptr()) })
138 }
139
140 pub fn get_param_table_str(
142 &self,
143 index: usize,
144 key: &str,
145 ) -> ScriptModuleCallHandleResult<Option<String>> {
146 let c_key = std::ffi::CString::new(key)
147 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
148 unsafe {
149 let c_str = ((*self.internal).get_param_table_string)(index as i32, c_key.as_ptr());
150 Ok(if c_str.is_null() {
151 None
152 } else {
153 Some(
154 std::ffi::CStr::from_ptr(c_str)
155 .to_string_lossy()
156 .into_owned(),
157 )
158 })
159 }
160 }
161
162 pub fn get_param_table_boolean(
168 &self,
169 index: usize,
170 key: &str,
171 ) -> ScriptModuleCallHandleResult<bool> {
172 let c_key = std::ffi::CString::new(key)
173 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
174 Ok(unsafe { ((*self.internal).get_param_table_boolean)(index as i32, c_key.as_ptr()) })
175 }
176
177 pub fn get_param_array_len(&self, index: usize) -> usize {
179 unsafe { ((*self.internal).get_param_array_num)(index as i32) as usize }
180 }
181
182 pub fn get_param_array_int(&self, index: usize, array_index: usize) -> i32 {
184 unsafe { ((*self.internal).get_param_array_int)(index as i32, array_index as i32) }
185 }
186
187 pub fn get_param_array_float(&self, index: usize, array_index: usize) -> f64 {
189 unsafe { ((*self.internal).get_param_array_double)(index as i32, array_index as i32) }
190 }
191
192 pub fn get_param_array_str(&self, index: usize, array_index: usize) -> Option<String> {
194 unsafe {
195 let c_str = ((*self.internal).get_param_array_string)(index as i32, array_index as i32);
196 if c_str.is_null() {
197 None
198 } else {
199 Some(
200 std::ffi::CStr::from_ptr(c_str)
201 .to_string_lossy()
202 .into_owned(),
203 )
204 }
205 }
206 }
207
208 pub fn set_error(&mut self, message: &str) -> ScriptModuleCallHandleResult<()> {
210 let c_message = std::ffi::CString::new(message)
211 .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
212 unsafe {
213 ((*self.internal).set_error)(c_message.as_ptr());
214 }
215 Ok(())
216 }
217
218 pub fn push_result<T: IntoScriptModuleReturnValue>(
220 &mut self,
221 value: T,
222 ) -> Result<(), IntoScriptModuleReturnValueError<T::Err>> {
223 value.push_into(self)
224 }
225
226 pub fn push_result_int(&mut self, value: i32) {
228 unsafe {
229 ((*self.internal).push_result_int)(value);
230 }
231 }
232
233 pub fn push_result_float(&mut self, value: f64) {
235 unsafe {
236 ((*self.internal).push_result_double)(value);
237 }
238 }
239
240 pub fn push_result_str(&mut self, value: &str) -> ScriptModuleCallHandleResult<()> {
242 let c_value = std::ffi::CString::new(value)
243 .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
244 unsafe {
245 ((*self.internal).push_result_string)(c_value.as_ptr());
246 }
247 Ok(())
248 }
249
250 pub fn push_result_data<T>(&mut self, value: *const T) {
252 unsafe {
253 ((*self.internal).push_result_data)(value as *const std::ffi::c_void);
254 }
255 }
256
257 pub fn push_result_table_int<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
259 where
260 T: std::iter::IntoIterator<Item = (&'a str, i32)>,
261 {
262 let mut keys = Vec::new();
263 let mut values = Vec::new();
264 for (key, value) in table {
265 let c_key = std::ffi::CString::new(key)
266 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
267 keys.push(c_key);
268 values.push(value);
269 }
270 let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
271 unsafe {
272 ((*self.internal).push_result_table_int)(
273 key_ptrs.as_ptr(),
274 values.as_ptr(),
275 key_ptrs.len() as i32,
276 );
277 }
278 Ok(())
279 }
280
281 pub fn push_result_table_float<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
283 where
284 T: std::iter::IntoIterator<Item = (&'a str, f64)>,
285 {
286 let mut keys = Vec::new();
287 let mut values = Vec::new();
288 for (key, value) in table {
289 let c_key = std::ffi::CString::new(key)
290 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
291 keys.push(c_key);
292 values.push(value);
293 }
294 let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
295 unsafe {
296 ((*self.internal).push_result_table_double)(
297 key_ptrs.as_ptr(),
298 values.as_ptr(),
299 key_ptrs.len() as i32,
300 );
301 }
302 Ok(())
303 }
304
305 pub fn push_result_table_str<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
307 where
308 T: std::iter::IntoIterator<Item = (&'a str, &'a str)>,
309 {
310 let mut keys = Vec::new();
311 let mut values = Vec::new();
312 for (key, value) in table {
313 let c_key = std::ffi::CString::new(key)
314 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
315 let c_value = std::ffi::CString::new(value)
316 .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
317 keys.push(c_key);
318 values.push(c_value);
319 }
320 if keys.len() > i32::MAX as usize {
321 return Err(ScriptModuleCallHandleError::TooManyElements);
322 }
323 let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
324 let value_ptrs: Vec<*const std::os::raw::c_char> =
325 values.iter().map(|v| v.as_ptr()).collect();
326 unsafe {
327 ((*self.internal).push_result_table_string)(
328 key_ptrs.as_ptr(),
329 value_ptrs.as_ptr(),
330 key_ptrs.len() as i32,
331 );
332 }
333 Ok(())
334 }
335
336 pub fn push_result_table_boolean<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
338 where
339 T: std::iter::IntoIterator<Item = (&'a str, bool)>,
340 {
341 let mut keys = Vec::new();
342 let mut values = Vec::new();
343 for (key, value) in table {
344 let c_key = std::ffi::CString::new(key)
345 .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
346 keys.push(c_key);
347 values.push(value);
348 }
349 let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
350 unsafe {
351 ((*self.internal).push_result_table_boolean)(
352 key_ptrs.as_ptr(),
353 values.as_ptr(),
354 key_ptrs.len() as i32,
355 );
356 }
357 Ok(())
358 }
359
360 pub fn push_result_array_int(&mut self, values: &[i32]) -> ScriptModuleCallHandleResult<()> {
362 if values.len() > i32::MAX as usize {
363 return Err(ScriptModuleCallHandleError::TooManyElements);
364 }
365 unsafe {
366 ((*self.internal).push_result_array_int)(values.as_ptr(), values.len() as i32);
367 }
368 Ok(())
369 }
370
371 pub fn push_result_array_float(&mut self, values: &[f64]) -> ScriptModuleCallHandleResult<()> {
373 if values.len() > i32::MAX as usize {
374 return Err(ScriptModuleCallHandleError::TooManyElements);
375 }
376 unsafe {
377 ((*self.internal).push_result_array_double)(values.as_ptr(), values.len() as i32);
378 }
379 Ok(())
380 }
381
382 pub fn push_result_array_str(&mut self, values: &[&str]) -> ScriptModuleCallHandleResult<()> {
384 let c_values: Vec<std::ffi::CString> = values
385 .iter()
386 .map(|s| std::ffi::CString::new(*s))
387 .collect::<Result<_, _>>()
388 .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
389 if c_values.len() > i32::MAX as usize {
390 return Err(ScriptModuleCallHandleError::TooManyElements);
391 }
392 let c_value_ptrs: Vec<*const std::os::raw::c_char> =
393 c_values.iter().map(|s| s.as_ptr()).collect();
394 unsafe {
395 ((*self.internal).push_result_array_string)(
396 c_value_ptrs.as_ptr(),
397 c_value_ptrs.len() as i32,
398 );
399 }
400 Ok(())
401 }
402
403 pub fn push_result_array_boolean(
405 &mut self,
406 values: &[bool],
407 ) -> ScriptModuleCallHandleResult<()> {
408 if values.len() > i32::MAX as usize {
409 return Err(ScriptModuleCallHandleError::TooManyElements);
410 }
411 unsafe {
412 ((*self.internal).push_result_array_boolean)(values.as_ptr(), values.len() as i32);
413 }
414 Ok(())
415 }
416
417 pub fn push_result_boolean(&mut self, value: bool) {
419 unsafe {
420 ((*self.internal).push_result_boolean)(value);
421 }
422 }
423}
424impl From<*mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM> for ScriptModuleCallHandle {
425 fn from(ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM) -> Self {
426 Self { internal: ptr }
427 }
428}
429
430pub trait FromScriptModuleParam<'a>: Sized {
437 fn from_param(param: &'a crate::module::ScriptModuleCallHandle, index: usize) -> Option<Self>;
438}
439
440pub use aviutl2_macros::FromScriptModuleParam;
441
442impl<'a> FromScriptModuleParam<'a> for i32 {
443 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
444 if index < param.len() {
445 Some(param.get_param_int(index))
446 } else {
447 None
448 }
449 }
450}
451#[duplicate::duplicate_item(
452 Integer Failable;
453 [i8] [true];
454 [i16] [true];
455 [i64] [false];
456 [i128] [false];
457 [isize] [false];
458 [u8] [true];
459 [u16] [true];
460 [u32] [true];
461 [u64] [false];
462 [u128] [false];
463 [usize] [false];
464)]
465impl<'a> FromScriptModuleParam<'a> for Integer {
466 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
467 if index < param.len() {
468 let value = param.get_param_int(index);
469 comptime_if::comptime_if!(
470 if failable where (failable = Failable) {
471 value.try_into().ok()
472 } else {
473 Some(value as Integer)
474 }
475 )
476 } else {
477 None
478 }
479 }
480}
481impl<'a> FromScriptModuleParam<'a> for f64 {
482 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
483 if index < param.len() {
484 Some(param.get_param_float(index))
485 } else {
486 None
487 }
488 }
489}
490impl<'a> FromScriptModuleParam<'a> for f32 {
491 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
492 if index < param.len() {
493 Some(param.get_param_float(index) as f32)
494 } else {
495 None
496 }
497 }
498}
499impl<'a> FromScriptModuleParam<'a> for bool {
500 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
501 if index < param.len() {
502 Some(param.get_param_boolean(index))
503 } else {
504 None
505 }
506 }
507}
508impl<'a> FromScriptModuleParam<'a> for String {
509 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
510 if index < param.len() {
511 param.get_param_str(index)
512 } else {
513 None
514 }
515 }
516}
517impl<'a, T> FromScriptModuleParam<'a> for NonNull<T> {
518 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
519 if index < param.len() {
520 param.get_param_data(index)
521 } else {
522 None
523 }
524 }
525}
526#[duplicate::duplicate_item(
527 Integer NonZero Failable;
528 [i8] [NonZeroI8] [true];
529 [i16] [NonZeroI16] [true];
530 [i64] [NonZeroI64] [false];
531 [i128] [NonZeroI128] [false];
532 [isize] [NonZeroIsize] [false];
533 [u8] [NonZeroU8] [true];
534 [u16] [NonZeroU16] [true];
535 [u32] [NonZeroU32] [true];
536 [u64] [NonZeroU64] [false];
537 [u128] [NonZeroU128] [false];
538 [usize] [NonZeroUsize] [false];
539)]
540impl<'a> FromScriptModuleParam<'a> for NonZero {
541 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
542 if index < param.len() {
543 let value: Integer = comptime_if::comptime_if!(
544 if failable where (failable = Failable) {
545 param.get_param_int(index).try_into().ok()?
546 } else {
547 param.get_param_int(index) as Integer
548 }
549 );
550 NonZero::new(value)
551 } else {
552 None
553 }
554 }
555}
556impl<'a> FromScriptModuleParam<'a> for NonZeroI32 {
557 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
558 if index < param.len() {
559 NonZeroI32::new(param.get_param_int(index))
560 } else {
561 None
562 }
563 }
564}
565
566impl<'a, T> FromScriptModuleParam<'a> for Option<T>
567where
568 T: FromScriptModuleParam<'a>,
569{
570 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
571 if index < param.len() {
572 Some(T::from_param(param, index))
573 } else {
574 None
575 }
576 }
577}
578
579pub struct ScriptModuleParamArray<'a> {
581 index: usize,
582 ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
583 marker: std::marker::PhantomData<&'a ()>,
584}
585
586impl std::fmt::Debug for ScriptModuleParamArray<'_> {
587 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
588 f.debug_struct("ScriptModuleParamArray")
589 .field("index", &self.index)
590 .field("len", &self.len())
591 .finish()
592 }
593}
594
595impl<'a> ScriptModuleParamArray<'a> {
596 pub fn len(&self) -> usize {
598 unsafe { ((*self.ptr).get_param_array_num)(self.index as i32) as usize }
599 }
600
601 pub fn is_empty(&self) -> bool {
603 self.len() == 0
604 }
605
606 pub fn get_int(&self, array_index: usize) -> i32 {
608 unsafe { ((*self.ptr).get_param_array_int)(self.index as i32, array_index as i32) }
609 }
610
611 pub fn get_float(&self, array_index: usize) -> f64 {
613 unsafe { ((*self.ptr).get_param_array_double)(self.index as i32, array_index as i32) }
614 }
615
616 pub fn get_str(&self, array_index: usize) -> Option<String> {
618 unsafe {
619 let c_str = ((*self.ptr).get_param_array_string)(self.index as i32, array_index as i32);
620 if c_str.is_null() {
621 None
622 } else {
623 Some(
624 std::ffi::CStr::from_ptr(c_str)
625 .to_string_lossy()
626 .into_owned(),
627 )
628 }
629 }
630 }
631}
632
633impl<'a> FromScriptModuleParam<'a> for ScriptModuleParamArray<'a> {
634 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
635 if index < param.len() {
636 Some(ScriptModuleParamArray {
637 index,
638 ptr: param.internal,
639 marker: std::marker::PhantomData,
640 })
641 } else {
642 None
643 }
644 }
645}
646
647#[derive(Debug)]
649pub struct ScriptModuleParamTable<'a> {
650 index: usize,
651 ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
652 marker: std::marker::PhantomData<&'a ()>,
653}
654
655impl<'a> ScriptModuleParamTable<'a> {
656 pub fn get_int(&self, key: &str) -> i32 {
658 let c_key = std::ffi::CString::new(key).unwrap();
659 unsafe { ((*self.ptr).get_param_table_int)(self.index as i32, c_key.as_ptr()) }
660 }
661
662 pub fn get_float(&self, key: &str) -> f64 {
664 let c_key = std::ffi::CString::new(key).unwrap();
665 unsafe { ((*self.ptr).get_param_table_double)(self.index as i32, c_key.as_ptr()) }
666 }
667
668 pub fn get_str(&self, key: &str) -> Option<String> {
670 let c_key = std::ffi::CString::new(key).unwrap();
671 unsafe {
672 let c_str = ((*self.ptr).get_param_table_string)(self.index as i32, c_key.as_ptr());
673 if c_str.is_null() {
674 None
675 } else {
676 Some(
677 std::ffi::CStr::from_ptr(c_str)
678 .to_string_lossy()
679 .into_owned(),
680 )
681 }
682 }
683 }
684
685 pub fn get_boolean(&self, key: &str) -> bool {
687 let c_key = std::ffi::CString::new(key).unwrap();
688 unsafe { ((*self.ptr).get_param_table_boolean)(self.index as i32, c_key.as_ptr()) }
689 }
690}
691
692impl<'a> FromScriptModuleParam<'a> for ScriptModuleParamTable<'a> {
693 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
694 if index < param.len() {
695 Some(ScriptModuleParamTable {
696 index,
697 ptr: param.internal,
698 marker: std::marker::PhantomData,
699 })
700 } else {
701 None
702 }
703 }
704}
705
706impl<'a> FromScriptModuleParam<'a> for Vec<String> {
707 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
708 let array = ScriptModuleParamArray::from_param(param, index)?;
709 let mut result = Vec::new();
710 for i in 0..array.len() {
711 result.push(array.get_str(i)?);
712 }
713 Some(result)
714 }
715}
716impl<'a> FromScriptModuleParam<'a> for Vec<i32> {
717 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
718 let array = ScriptModuleParamArray::from_param(param, index)?;
719 let mut result = Vec::new();
720 for i in 0..array.len() {
721 result.push(array.get_int(i));
722 }
723 Some(result)
724 }
725}
726impl<'a> FromScriptModuleParam<'a> for Vec<f64> {
727 fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> Option<Self> {
728 let array = ScriptModuleParamArray::from_param(param, index)?;
729 let mut result = Vec::new();
730 for i in 0..array.len() {
731 result.push(array.get_float(i));
732 }
733 Some(result)
734 }
735}
736
737pub trait FromScriptModuleParamTable<'a>: Sized {
739 fn from_param_table(
740 param: &'a crate::module::ScriptModuleParamTable,
741 key: &str,
742 ) -> Option<Self>;
743}
744
745impl<'a> FromScriptModuleParamTable<'a> for i32 {
746 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
747 Some(param.get_int(key))
748 }
749}
750#[duplicate::duplicate_item(
751 Integer Failable;
752 [i8] [true];
753 [i16] [true];
754 [i64] [false];
755 [i128] [false];
756 [isize] [false];
757 [u8] [true];
758 [u16] [true];
759 [u32] [true];
760 [u64] [false];
761 [u128] [false];
762 [usize] [false];
763)]
764impl<'a> FromScriptModuleParamTable<'a> for Integer {
765 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
766 let value = param.get_int(key);
767 comptime_if::comptime_if!(
768 if failable where (failable = Failable) {
769 value.try_into().ok()
770 } else {
771 Some(value as Integer)
772 }
773 )
774 }
775}
776impl<'a> FromScriptModuleParamTable<'a> for f64 {
777 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
778 Some(param.get_float(key))
779 }
780}
781impl<'a> FromScriptModuleParamTable<'a> for f32 {
782 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
783 Some(param.get_float(key) as f32)
784 }
785}
786impl<'a> FromScriptModuleParamTable<'a> for String {
787 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
788 param.get_str(key)
789 }
790}
791impl<'a> FromScriptModuleParamTable<'a> for bool {
792 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
793 Some(param.get_boolean(key))
794 }
795}
796impl<'a, T: FromScriptModuleParamTable<'a>> FromScriptModuleParamTable<'a> for Option<T> {
797 fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> Option<Self> {
798 Some(T::from_param_table(param, key))
799 }
800}
801
802#[derive(Debug, Clone)]
804pub enum ScriptModuleReturnValue {
805 Int(i32),
806 Float(f64),
807 String(String),
808 Boolean(bool),
809 Data(*const std::ffi::c_void),
810 StringArray(Vec<String>),
811 IntArray(Vec<i32>),
812 FloatArray(Vec<f64>),
813 IntTable(std::collections::HashMap<String, i32>),
814 FloatTable(std::collections::HashMap<String, f64>),
815 StringTable(std::collections::HashMap<String, String>),
816}
817
818#[derive(thiserror::Error, Debug)]
820pub enum IntoScriptModuleReturnValueError<T> {
821 #[error("failed to convert value: {0}")]
822 ConversionFailed(#[source] T),
823 #[error("failed to push return value: {0}")]
824 PushFailed(#[from] ScriptModuleCallHandleError),
825}
826
827pub trait IntoScriptModuleReturnValue
834where
835 Self: Sized,
836{
837 type Err: Send + Sync + 'static + Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
838
839 fn into_return_values(self) -> Result<Vec<crate::module::ScriptModuleReturnValue>, Self::Err>;
840 fn push_into(
841 self,
842 param: &mut crate::module::ScriptModuleCallHandle,
843 ) -> Result<(), crate::module::IntoScriptModuleReturnValueError<Self::Err>> {
844 for value in self
845 .into_return_values()
846 .map_err(IntoScriptModuleReturnValueError::ConversionFailed)?
847 {
848 match value {
849 ScriptModuleReturnValue::Int(v) => {
850 param.push_result_int(v);
851 }
852 ScriptModuleReturnValue::Float(v) => {
853 param.push_result_float(v);
854 }
855 ScriptModuleReturnValue::String(v) => {
856 param.push_result_str(&v)?;
857 }
858 ScriptModuleReturnValue::Boolean(v) => {
859 param.push_result_boolean(v);
860 }
861 ScriptModuleReturnValue::Data(v) => {
862 param.push_result_data(v);
863 }
864 ScriptModuleReturnValue::StringArray(v) => {
865 let strs: Vec<&str> = v.iter().map(|s| s.as_str()).collect();
866 param.push_result_array_str(&strs)?
867 }
868 ScriptModuleReturnValue::IntArray(v) => param.push_result_array_int(&v)?,
869 ScriptModuleReturnValue::FloatArray(v) => param.push_result_array_float(&v)?,
870 ScriptModuleReturnValue::IntTable(v) => {
871 let table = v.iter().map(|(k, v)| (k.as_str(), *v));
872 param.push_result_table_int(table)?;
873 }
874 ScriptModuleReturnValue::FloatTable(v) => {
875 let table = v.iter().map(|(k, v)| (k.as_str(), *v));
876 param.push_result_table_float(table)?;
877 }
878 ScriptModuleReturnValue::StringTable(v) => {
879 let table = v.iter().map(|(k, v)| (k.as_str(), v.as_str()));
880 param.push_result_table_str(table)?;
881 }
882 };
883 }
884 Ok(())
885 }
886}
887pub use aviutl2_macros::IntoScriptModuleReturnValue;
888
889impl<T> IntoScriptModuleReturnValue for *const T {
890 type Err = std::convert::Infallible;
891
892 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
893 Ok(vec![ScriptModuleReturnValue::Data(
894 self as *const std::ffi::c_void,
895 )])
896 }
897}
898
899impl IntoScriptModuleReturnValue for i32 {
900 type Err = std::convert::Infallible;
901
902 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
903 Ok(vec![ScriptModuleReturnValue::Int(self)])
904 }
905}
906#[duplicate::duplicate_item(
907 Integer;
908 [i8];
909 [i16];
910 [u8];
911 [u16];
912)]
913impl IntoScriptModuleReturnValue for Integer {
914 type Err = std::convert::Infallible;
915
916 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
917 Ok(vec![ScriptModuleReturnValue::Int(self as i32)])
918 }
919}
920#[duplicate::duplicate_item(
921 Integer;
922 [i64];
923 [i128];
924 [isize];
925 [u32];
926 [u64];
927 [u128];
928 [usize];
929)]
930impl IntoScriptModuleReturnValue for Integer {
931 type Err = std::num::TryFromIntError;
932
933 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
934 Ok(vec![ScriptModuleReturnValue::Int(self.try_into()?)])
935 }
936}
937impl IntoScriptModuleReturnValue for f64 {
938 type Err = std::convert::Infallible;
939 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
940 Ok(vec![ScriptModuleReturnValue::Float(self)])
941 }
942}
943impl IntoScriptModuleReturnValue for f32 {
944 type Err = std::convert::Infallible;
945 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
946 Ok(vec![ScriptModuleReturnValue::Float(self as f64)])
947 }
948}
949impl IntoScriptModuleReturnValue for bool {
950 type Err = std::convert::Infallible;
951 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
952 Ok(vec![ScriptModuleReturnValue::Boolean(self)])
953 }
954}
955impl IntoScriptModuleReturnValue for &str {
956 type Err = std::convert::Infallible;
957 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
958 Ok(vec![ScriptModuleReturnValue::String(self.to_string())])
959 }
960}
961impl IntoScriptModuleReturnValue for String {
962 type Err = std::convert::Infallible;
963 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
964 Ok(vec![ScriptModuleReturnValue::String(self)])
965 }
966}
967
968impl IntoScriptModuleReturnValue for ScriptModuleReturnValue {
969 type Err = std::convert::Infallible;
970 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
971 Ok(vec![self])
972 }
973}
974
975impl IntoScriptModuleReturnValue for Vec<ScriptModuleReturnValue> {
976 type Err = std::convert::Infallible;
977
978 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
979 Ok(self)
980 }
981}
982
983impl<T: IntoScriptModuleReturnValue> IntoScriptModuleReturnValue for Option<T> {
984 type Err = T::Err;
985 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
986 if let Some(value) = self {
987 value.into_return_values()
988 } else {
989 Ok(Vec::new())
990 }
991 }
992}
993impl<T, const N: usize> IntoScriptModuleReturnValue for [T; N]
994where
995 Vec<T>: IntoScriptModuleReturnValue,
996{
997 type Err = <Vec<T> as IntoScriptModuleReturnValue>::Err;
998
999 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1000 let vec: Vec<T> = self.into();
1001 vec.into_return_values()
1002 }
1003}
1004impl<T: IntoScriptModuleReturnValue, E> IntoScriptModuleReturnValue for Result<T, E>
1005where
1006 E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
1007{
1008 type Err = T::Err;
1009
1010 fn into_return_values(
1011 self,
1012 ) -> Result<
1013 Vec<ScriptModuleReturnValue>,
1014 <std::result::Result<T, E> as IntoScriptModuleReturnValue>::Err,
1015 > {
1016 match self {
1017 Ok(value) => value.into_return_values(),
1018 Err(_) => Ok(Vec::new()),
1019 }
1020 }
1021 fn push_into(
1022 self,
1023 param: &mut ScriptModuleCallHandle,
1024 ) -> Result<
1025 (),
1026 IntoScriptModuleReturnValueError<
1027 <std::result::Result<T, E> as IntoScriptModuleReturnValue>::Err,
1028 >,
1029 > {
1030 match self {
1031 Ok(value) => value.push_into(param)?,
1032 Err(err) => {
1033 let e: Box<dyn std::error::Error + 'static> = err.into();
1034 let e = e.to_string();
1035 param.set_error(&e)?
1036 }
1037 }
1038 Ok(())
1039 }
1040}
1041
1042impl IntoScriptModuleReturnValue for () {
1043 type Err = std::convert::Infallible;
1044 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1045 Ok(Vec::new())
1046 }
1047}
1048
1049macro_rules! impl_into_script_module_return_value_for_tuple {
1050 ($($name:ident),+) => {
1051 impl<$($name),+> IntoScriptModuleReturnValue for ($($name,)+)
1052 where
1053 $($name: IntoScriptModuleReturnValue),+
1054 {
1055 type Err = anyhow::Error;
1056
1057 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1058 let mut vec = Vec::new();
1059 #[allow(non_snake_case)]
1060 let ($($name,)+) = self;
1061 $(
1062 vec.extend(
1063 $name.into_return_values()
1064 .map_err(|e| anyhow::Error::from_boxed(e.into()))?
1065 );
1066 )+
1067 Ok(vec)
1068 }
1069 }
1070 };
1071}
1072impl_into_script_module_return_value_for_tuple!(T1);
1073impl_into_script_module_return_value_for_tuple!(T1, T2);
1074impl_into_script_module_return_value_for_tuple!(T1, T2, T3);
1075impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4);
1076impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5);
1077impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6);
1078impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7);
1079impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
1080impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
1081impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
1082
1083impl IntoScriptModuleReturnValue for Vec<String> {
1084 type Err = std::convert::Infallible;
1085 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1086 Ok(vec![ScriptModuleReturnValue::StringArray(self)])
1087 }
1088}
1089impl IntoScriptModuleReturnValue for Vec<&str> {
1090 type Err = std::convert::Infallible;
1091 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1092 Ok(vec![ScriptModuleReturnValue::StringArray(
1093 self.iter().map(|s| s.to_string()).collect(),
1094 )])
1095 }
1096}
1097impl IntoScriptModuleReturnValue for Vec<i32> {
1098 type Err = std::convert::Infallible;
1099 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1100 Ok(vec![ScriptModuleReturnValue::IntArray(self)])
1101 }
1102}
1103impl IntoScriptModuleReturnValue for Vec<f64> {
1104 type Err = std::convert::Infallible;
1105 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1106 Ok(vec![ScriptModuleReturnValue::FloatArray(self)])
1107 }
1108}
1109impl<T> IntoScriptModuleReturnValue for &[T]
1110where
1111 Vec<T>: IntoScriptModuleReturnValue,
1112 T: Clone,
1113{
1114 type Err = <Vec<T> as IntoScriptModuleReturnValue>::Err;
1115 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1116 let vec: Vec<T> = self.to_vec();
1117 vec.into_return_values()
1118 }
1119}
1120
1121impl IntoScriptModuleReturnValue for std::collections::HashMap<String, i32> {
1122 type Err = std::convert::Infallible;
1123 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1124 Ok(vec![ScriptModuleReturnValue::IntTable(self)])
1125 }
1126}
1127impl IntoScriptModuleReturnValue for std::collections::HashMap<String, f64> {
1128 type Err = std::convert::Infallible;
1129 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1130 Ok(vec![ScriptModuleReturnValue::FloatTable(self)])
1131 }
1132}
1133impl IntoScriptModuleReturnValue for std::collections::HashMap<String, String> {
1134 type Err = std::convert::Infallible;
1135 fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1136 Ok(vec![ScriptModuleReturnValue::StringTable(self)])
1137 }
1138}
1139
1140#[doc(hidden)]
1141pub mod __table_converter {
1142 pub trait ToOptionalTableEntry {
1143 type Value;
1144 fn to_optional(&self) -> Option<Self::Value>;
1145 }
1146
1147 impl<T: Clone> ToOptionalTableEntry for Option<T> {
1148 type Value = T;
1149 fn to_optional(&self) -> Option<Self::Value> {
1150 self.clone()
1151 }
1152 }
1153 impl ToOptionalTableEntry for i32 {
1154 type Value = i32;
1155 fn to_optional(&self) -> Option<Self::Value> {
1156 Some(*self)
1157 }
1158 }
1159 impl ToOptionalTableEntry for f64 {
1160 type Value = f64;
1161 fn to_optional(&self) -> Option<Self::Value> {
1162 Some(*self)
1163 }
1164 }
1165 impl ToOptionalTableEntry for String {
1166 type Value = String;
1167 fn to_optional(&self) -> Option<Self::Value> {
1168 Some(self.clone())
1169 }
1170 }
1171}
1172
1173#[doc(hidden)]
1174pub fn __push_return_value<T>(param: &mut crate::module::ScriptModuleCallHandle, value: T)
1175where
1176 T: crate::module::IntoScriptModuleReturnValue,
1177{
1178 let res = value.push_into(param);
1179 let _ = res
1180 .map_err(|e| -> Box<dyn std::error::Error + Send + Sync + 'static> {
1181 match e {
1182 crate::module::IntoScriptModuleReturnValueError::PushFailed(e) => Box::new(e),
1183 crate::module::IntoScriptModuleReturnValueError::ConversionFailed(e) => e.into(),
1184 }
1185 })
1186 .push_into(param);
1187}