Skip to main content

aviutl2\module/
param.rs

1use std::num::{
2    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
3    NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
4};
5use std::ptr::NonNull;
6
7/// 関数の引数・返り値を扱うための型とトレイト。
8#[derive(Debug)]
9pub struct ScriptModuleCallHandle {
10    pub(crate) internal: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
11}
12
13/// [`ScriptModuleCallHandle`]関連のエラー。
14#[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    /// ポインタから`ScriptModuleParam`を作成する。
30    ///
31    /// # Safety
32    ///
33    /// `ptr`は有効な`SCRIPT_MODULE_PARAM`へのポインタである必要があります。
34    pub unsafe fn from_raw(
35        ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
36    ) -> ScriptModuleCallHandle {
37        ScriptModuleCallHandle { internal: ptr }
38    }
39
40    /// 引数の数を返す。
41    pub fn len(&self) -> usize {
42        unsafe { ((*self.internal).get_param_num)() as usize }
43    }
44
45    /// 引数が与えられていないかを返す。
46    pub fn is_empty(&self) -> bool {
47        self.len() == 0
48    }
49
50    /// 引数を取得する。
51    pub fn get_param<'a, T: FromScriptModuleParam<'a>>(&'a self, index: usize) -> Option<T> {
52        T::from_param(self, index)
53    }
54
55    /// 引数を整数として取得する。
56    ///
57    /// # Note
58    ///
59    /// 引数を取得できない場合は0を返します。
60    pub fn get_param_int(&self, index: usize) -> i32 {
61        unsafe { ((*self.internal).get_param_int)(index as i32) }
62    }
63
64    /// 引数を浮動小数点数として取得する。
65    ///
66    /// # Note
67    ///
68    /// 引数を取得できない場合は0.0を返します。
69    pub fn get_param_float(&self, index: usize) -> f64 {
70        unsafe { ((*self.internal).get_param_double)(index as i32) }
71    }
72
73    /// 引数を文字列として取得する。
74    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    /// 引数をデータポインタとして取得する。
90    ///
91    /// # Note
92    ///
93    /// 引数を取得できない場合は`None`を返します。
94    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    /// 引数をブール値として取得する。
102    ///
103    /// # Note
104    ///
105    /// 引数を取得できない場合は`false`を返します。
106    pub fn get_param_boolean(&self, index: usize) -> bool {
107        unsafe { ((*self.internal).get_param_boolean)(index as i32) }
108    }
109
110    /// 引数のテーブルの要素を整数として取得する。
111    ///
112    /// # Note
113    ///
114    /// 引数を取得できない場合は0を返します。
115    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    /// 引数のテーブルの要素を浮動小数点数として取得する。
126    ///
127    /// # Note
128    ///
129    /// 引数を取得できない場合は0.0を返します。
130    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    /// 引数のテーブルの要素を文字列として取得する。
141    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    /// 引数のテーブルの要素をブール値として取得する。
163    ///
164    /// # Note
165    ///
166    /// 引数を取得できない場合は`false`を返します。
167    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    /// 引数の配列の要素の数を取得する。
178    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    /// 引数の配列の要素を数値として取得する。
183    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    /// 引数の配列の要素を浮動小数点数として取得する。
188    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    /// 引数の配列の要素を文字列として取得する。
193    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    /// 関数のエラーを設定する。
209    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    /// 関数の返り値を追加する。
219    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    /// 関数の返り値に整数を追加する。
227    pub fn push_result_int(&mut self, value: i32) {
228        unsafe {
229            ((*self.internal).push_result_int)(value);
230        }
231    }
232
233    /// 関数の返り値に浮動小数点数を追加する。
234    pub fn push_result_float(&mut self, value: f64) {
235        unsafe {
236            ((*self.internal).push_result_double)(value);
237        }
238    }
239
240    /// 関数の返り値に文字列を追加する。
241    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    /// 関数の返り値にデータポインタを追加する。
251    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    /// 関数の返り値に整数の連想配列を追加する。
258    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    /// 関数の返り値に浮動小数点数の連想配列を追加する。
282    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    /// 関数の返り値に文字列の連想配列を追加する。
306    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    /// 関数の返り値にブール値の連想配列を追加する。
337    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    /// 関数の返り値に整数の配列を追加する。
361    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    /// 関数の返り値に浮動小数点数の配列を追加する。
372    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    /// 関数の返り値に文字列の配列を追加する。
383    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    /// 関数の返り値にブール値の配列を追加する。
404    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    /// 関数の返り値にブール値を追加する。
418    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
430/// スクリプトモジュールの引数として受け取れる値。
431///
432/// # Note
433///
434/// このtraitはDeriveマクロを使用して実装することもできます。
435/// 詳細は[`derive@FromScriptModuleParam`]のドキュメントを参照してください。
436pub 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
579/// スクリプトモジュールの引数として渡される配列。
580pub 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    /// 配列の長さを返す。
597    pub fn len(&self) -> usize {
598        unsafe { ((*self.ptr).get_param_array_num)(self.index as i32) as usize }
599    }
600
601    /// 配列が空かどうかを返す。
602    pub fn is_empty(&self) -> bool {
603        self.len() == 0
604    }
605
606    /// 配列の要素を整数として取得する。
607    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    /// 配列の要素を浮動小数点数として取得する。
612    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    /// 配列の要素を文字列として取得する。
617    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/// スクリプトモジュールの引数として渡される連想配列。
648#[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    /// 連想配列の要素を整数として取得する。
657    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    /// 連想配列の要素を浮動小数点数として取得する。
663    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    /// 連想配列の要素を文字列として取得する。
669    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    /// 連想配列の要素をブール値として取得する。
686    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
737/// 連想配列の値として使える型。
738pub 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/// スクリプトモジュールの関数の戻り値の型を表す列挙型。
803#[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/// [`IntoScriptModuleReturnValue::push_into`]で使われるエラー。
819#[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
827/// 関数の戻り値として使える型。
828///
829/// # Note
830///
831/// この関数はDeriveマクロを使用して実装することもできます。
832/// 詳細は[`derive@IntoScriptModuleReturnValue`]のドキュメントを参照してください。
833pub 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}