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    pub(crate) read_section: crate::generic::ReadSection,
12}
13
14/// [`ScriptModuleCallHandle`]関連のエラー。
15#[derive(thiserror::Error, Debug)]
16pub enum ScriptModuleCallHandleError<E: std::fmt::Debug = std::convert::Infallible> {
17    #[error("expected {expected:?}, but got {actual:?}")]
18    TypeMismatch {
19        /// 期待される型。
20        expected: ParamType,
21        /// 実際の型。
22        actual: ParamType,
23    },
24
25    #[error("key contains null byte")]
26    KeyContainsNullByte(std::ffi::NulError),
27
28    #[error("value contains null byte")]
29    ValueContainsNullByte(std::ffi::NulError),
30
31    #[error("too many elements")]
32    TooManyElements,
33
34    #[error("failed to convert value: {0}")]
35    ConversionError(E),
36}
37
38pub type ScriptModuleCallHandleResult<T, E = std::convert::Infallible> =
39    std::result::Result<T, ScriptModuleCallHandleError<E>>;
40
41impl ScriptModuleCallHandleError<std::convert::Infallible> {
42    fn into_conversion_error<E: std::fmt::Debug>(self) -> ScriptModuleCallHandleError<E> {
43        match self {
44            ScriptModuleCallHandleError::TypeMismatch { expected, actual } => {
45                ScriptModuleCallHandleError::TypeMismatch { expected, actual }
46            }
47            ScriptModuleCallHandleError::KeyContainsNullByte(error) => {
48                ScriptModuleCallHandleError::KeyContainsNullByte(error)
49            }
50            ScriptModuleCallHandleError::ValueContainsNullByte(error) => {
51                ScriptModuleCallHandleError::ValueContainsNullByte(error)
52            }
53            ScriptModuleCallHandleError::TooManyElements => {
54                ScriptModuleCallHandleError::TooManyElements
55            }
56            ScriptModuleCallHandleError::ConversionError(error) => match error {},
57        }
58    }
59}
60
61/// スクリプトモジュールの整数値から変換できる型。
62pub trait FromScriptModuleInteger: Sized {
63    type Error: std::fmt::Debug;
64
65    fn from_script_module_integer(value: i32) -> Result<Self, Self::Error>;
66}
67
68#[duplicate::duplicate_item(
69    Integer;
70    [i8];
71    [i16];
72    [isize];
73    [u8];
74    [u16];
75    [u32];
76    [u64];
77    [u128];
78    [usize];
79)]
80impl FromScriptModuleInteger for Integer {
81    type Error = <Self as TryFrom<i32>>::Error;
82
83    fn from_script_module_integer(value: i32) -> Result<Self, Self::Error> {
84        value.try_into()
85    }
86}
87impl FromScriptModuleInteger for i32 {
88    type Error = std::convert::Infallible;
89
90    fn from_script_module_integer(value: i32) -> Result<Self, Self::Error> {
91        Ok(value)
92    }
93}
94#[duplicate::duplicate_item(
95    Integer;
96    [i64];
97    [i128];
98)]
99impl FromScriptModuleInteger for Integer {
100    type Error = std::convert::Infallible;
101
102    fn from_script_module_integer(value: i32) -> Result<Self, Self::Error> {
103        Ok(value.into())
104    }
105}
106
107fn convert_script_module_integer<T>(value: i32) -> ScriptModuleCallHandleResult<T, T::Error>
108where
109    T: FromScriptModuleInteger,
110{
111    T::from_script_module_integer(value).map_err(ScriptModuleCallHandleError::ConversionError)
112}
113
114/// `push_result_function` で返すスクリプトモジュール関数コールバック。
115#[derive(Debug, Clone, Copy)]
116pub struct ScriptModuleFunctionCallback {
117    pub func: unsafe extern "C" fn(*mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM),
118    pub userdata: *mut std::ffi::c_void,
119}
120
121/// ユーザーデータとして相互変換する構造体。
122pub struct ScriptModuleUserData<T: Send + Sync + 'static + AsScriptModuleUserData> {
123    data: std::sync::Arc<std::sync::Mutex<T>>,
124}
125
126struct MetaMethodFunctionTableEntry {
127    meta_method_functions: Box<[aviutl2_sys::module2::META_METHOD_FUNCTION]>,
128}
129unsafe impl Send for MetaMethodFunctionTableEntry {}
130unsafe impl Sync for MetaMethodFunctionTableEntry {}
131
132// META_METHOD_FUNCTIONSは型ごとに一度だけ作成される必要があるため、型ごとにヒープに乗せて
133// そのポインタを使うようにする。
134fn type_to_meta_method_functions<T: Send + Sync + 'static + AsScriptModuleUserData>()
135-> *const aviutl2_sys::module2::META_METHOD_FUNCTION {
136    static META_METHOD_FUNCTIONS: std::sync::LazyLock<
137        dashmap::DashMap<std::any::TypeId, MetaMethodFunctionTableEntry>,
138    > = std::sync::LazyLock::new(Default::default);
139
140    let type_id = std::any::TypeId::of::<T>();
141    META_METHOD_FUNCTIONS
142        .entry(type_id)
143        .or_insert_with(|| {
144            let last = T::META_METHOD_FUNCTIONS.last();
145            assert!(
146                last.is_some() && last.unwrap().method.is_null(),
147                "META_METHOD_FUNCTIONS must be null-terminated"
148            );
149            MetaMethodFunctionTableEntry {
150                meta_method_functions: T::META_METHOD_FUNCTIONS.to_vec().into_boxed_slice(),
151            }
152        })
153        .meta_method_functions
154        .as_ptr()
155}
156
157/// [ScriptModuleUserData]から型パラメータを消去した構造体。
158#[derive(Debug)]
159pub struct ErasedScriptModuleUserData {
160    pub meta_method_functions: *const aviutl2_sys::module2::META_METHOD_FUNCTION,
161    pub userdata: *mut std::ffi::c_void,
162}
163
164impl<T: Send + Sync + 'static + AsScriptModuleUserData> From<ScriptModuleUserData<T>>
165    for ErasedScriptModuleUserData
166{
167    fn from(meta_table: ScriptModuleUserData<T>) -> Self {
168        let data = Box::into_raw(Box::new(meta_table.data)) as *mut std::ffi::c_void;
169        let meta_method_functions = type_to_meta_method_functions::<T>();
170        ErasedScriptModuleUserData {
171            meta_method_functions,
172            userdata: data,
173        }
174    }
175}
176impl<T: Send + Sync + 'static + AsScriptModuleUserData> ScriptModuleUserData<T> {
177    /// 新しいメタテーブルを作成する。
178    pub fn new(data: T) -> Self {
179        ScriptModuleUserData {
180            data: std::sync::Arc::new(std::sync::Mutex::new(data)),
181        }
182    }
183
184    /// メタテーブルのユーザーデータを取得する。
185    pub fn lock(
186        &self,
187    ) -> Result<std::sync::MutexGuard<'_, T>, std::sync::PoisonError<std::sync::MutexGuard<'_, T>>>
188    {
189        self.data.lock()
190    }
191}
192impl<T: Send + Sync + 'static + AsScriptModuleUserData> From<T> for ScriptModuleUserData<T> {
193    fn from(data: T) -> Self {
194        ScriptModuleUserData::new(data)
195    }
196}
197
198unsafe extern "C" fn dummy_meta_method_function(
199    _smp: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
200) {
201    // 何もしない
202}
203unsafe extern "C" fn script_module_user_data_gc<
204    T: Send + Sync + 'static + AsScriptModuleUserData,
205>(
206    smp: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
207) {
208    let userdata = unsafe { (*smp).userdata };
209    if !userdata.is_null() {
210        unsafe {
211            drop(Box::<std::sync::Arc<std::sync::Mutex<T>>>::from_raw(
212                userdata as *mut std::sync::Arc<std::sync::Mutex<T>>,
213            ));
214        }
215    }
216}
217
218/// ユーザーデータとして変換できる型のトレイト。
219///
220/// # Note
221///
222/// [`crate::module::metatable`]を使うと自動的に実装されます。
223pub trait AsScriptModuleUserData: Send + Sync + Sized + 'static {
224    const META_METHOD_FUNCTIONS: &'static [aviutl2_sys::module2::META_METHOD_FUNCTION] = &[
225        aviutl2_sys::module2::META_METHOD_FUNCTION {
226            method: c"__gc".as_ptr(),
227            func: script_module_user_data_gc::<Self>,
228        },
229        aviutl2_sys::module2::META_METHOD_FUNCTION {
230            method: std::ptr::null(),
231            func: dummy_meta_method_function,
232        },
233    ];
234}
235
236/// スクリプトモジュールで渡された引数の型。
237///
238/// # See Also
239///
240/// <https://www.lua.org/pil/2.html>
241#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242pub enum ParamType {
243    Nil,
244    Boolean,
245    LightUserdata,
246    Number,
247    String,
248    Table,
249    Function,
250    Userdata,
251    Thread,
252}
253
254/// 引数の取得に失敗した場合のエラー。
255#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
256pub enum GetParamError<T: std::fmt::Debug> {
257    #[error("expected {expected:?}, but got {actual:?}")]
258    TypeMismatch {
259        /// 期待される型。
260        expected: ParamType,
261        /// 実際の型。
262        actual: ParamType,
263    },
264    #[error("index {index} is out of bounds, {len} given")]
265    IndexOutOfBounds {
266        /// 取得しようとした引数のインデックス。
267        index: usize,
268        /// 引数の総数。
269        len: usize,
270    },
271    #[error("failed to convert value: {0}")]
272    ConversionError(T),
273}
274pub type GetParamResult<T, E = std::convert::Infallible> = std::result::Result<T, GetParamError<E>>;
275
276/// 引数変換に失敗した場合のエラー。
277#[derive(Debug, thiserror::Error)]
278#[error("{message}")]
279pub struct ParamConversionError {
280    message: String,
281}
282
283impl ParamConversionError {
284    pub fn new(message: impl Into<String>) -> Self {
285        Self {
286            message: message.into(),
287        }
288    }
289}
290
291impl GetParamError<std::convert::Infallible> {
292    fn into_conversion_error<T: std::fmt::Debug>(self) -> GetParamError<T> {
293        match self {
294            GetParamError::TypeMismatch { expected, actual } => {
295                GetParamError::TypeMismatch { expected, actual }
296            }
297            GetParamError::IndexOutOfBounds { index, len } => {
298                GetParamError::IndexOutOfBounds { index, len }
299            }
300            GetParamError::ConversionError(error) => match error {},
301        }
302    }
303}
304
305impl ScriptModuleCallHandle {
306    /// ポインタから`ScriptModuleParam`を作成する。
307    ///
308    /// # Safety
309    ///
310    /// `ptr`は有効な`SCRIPT_MODULE_PARAM`へのポインタである必要があります。
311    pub unsafe fn from_raw(
312        ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
313    ) -> ScriptModuleCallHandle {
314        ScriptModuleCallHandle {
315            internal: ptr,
316            read_section: unsafe { crate::generic::ReadSection::from_raw((*ptr).edit) },
317        }
318    }
319
320    /// 引数の数を返す。
321    pub fn len(&self) -> usize {
322        unsafe { ((*self.internal).get_param_num)() as usize }
323    }
324
325    /// 引数が与えられていないかを返す。
326    pub fn is_empty(&self) -> bool {
327        self.len() == 0
328    }
329
330    /// 渡された引数の型を取得する。
331    ///
332    /// # Note
333    ///
334    /// 引数が渡されていない場合は`None`を返します。
335    pub fn get_param_type(&self, index: usize) -> Option<ParamType> {
336        let param_type = unsafe { ((*self.internal).get_param_type)(index as i32) };
337        match param_type {
338            aviutl2_sys::module2::PARAM_TYPE::NONE => None,
339            aviutl2_sys::module2::PARAM_TYPE::NIL => Some(ParamType::Nil),
340            aviutl2_sys::module2::PARAM_TYPE::BOOLEAN => Some(ParamType::Boolean),
341            aviutl2_sys::module2::PARAM_TYPE::LIGHTUSERDATA => Some(ParamType::LightUserdata),
342            aviutl2_sys::module2::PARAM_TYPE::NUMBER => Some(ParamType::Number),
343            aviutl2_sys::module2::PARAM_TYPE::STRING => Some(ParamType::String),
344            aviutl2_sys::module2::PARAM_TYPE::TABLE => Some(ParamType::Table),
345            aviutl2_sys::module2::PARAM_TYPE::FUNCTION => Some(ParamType::Function),
346            aviutl2_sys::module2::PARAM_TYPE::USERDATA => Some(ParamType::Userdata),
347            aviutl2_sys::module2::PARAM_TYPE::THREAD => Some(ParamType::Thread),
348        }
349    }
350
351    fn assert_param_type(&self, index: usize, expected: ParamType) -> GetParamResult<()> {
352        let actual = self
353            .get_param_type(index)
354            .ok_or(GetParamError::IndexOutOfBounds {
355                index,
356                len: self.len(),
357            })?;
358        if actual != expected {
359            return Err(GetParamError::TypeMismatch { expected, actual });
360        }
361        Ok(())
362    }
363
364    fn assert_param_type_for_call(
365        &self,
366        index: usize,
367        expected: ParamType,
368    ) -> ScriptModuleCallHandleResult<()> {
369        let Some(actual) = self.get_param_type(index) else {
370            return Ok(());
371        };
372        if actual != expected {
373            return Err(ScriptModuleCallHandleError::TypeMismatch { expected, actual });
374        }
375        Ok(())
376    }
377
378    /// 引数を取得する。
379    pub fn get_param<'a, T: FromScriptModuleParam<'a>>(
380        &'a self,
381        index: usize,
382    ) -> GetParamResult<T, T::Error> {
383        T::from_param(self, index)
384    }
385
386    /// 引数を整数として取得する。
387    pub fn get_param_int(&self, index: usize) -> GetParamResult<i32> {
388        self.assert_param_type(index, ParamType::Number)?;
389        Ok(unsafe { ((*self.internal).get_param_int)(index as i32) })
390    }
391
392    /// 引数を浮動小数点数として取得する。
393    pub fn get_param_float(&self, index: usize) -> GetParamResult<f64> {
394        self.assert_param_type(index, ParamType::Number)?;
395        Ok(unsafe { ((*self.internal).get_param_double)(index as i32) })
396    }
397
398    /// 引数を文字列として取得する。
399    pub fn get_param_str(&self, index: usize) -> GetParamResult<String> {
400        self.assert_param_type(index, ParamType::String)?;
401        unsafe {
402            let c_str = ((*self.internal).get_param_string)(index as i32);
403            assert!(!c_str.is_null(), "get_param_string returned null");
404            Ok(std::ffi::CStr::from_ptr(c_str)
405                .to_string_lossy()
406                .into_owned())
407        }
408    }
409
410    /// 引数をデータポインタとして取得する。
411    pub fn get_param_data<T>(&self, index: usize) -> GetParamResult<*mut T> {
412        // self.assert_param_type(index, ParamType::LightUserdata)?;
413        let param_type = self
414            .get_param_type(index)
415            .ok_or(GetParamError::IndexOutOfBounds {
416                index,
417                len: self.len(),
418            })?;
419        if param_type != ParamType::LightUserdata && param_type != ParamType::Userdata {
420            return Err(GetParamError::TypeMismatch {
421                expected: ParamType::LightUserdata,
422                actual: param_type,
423            });
424        }
425        unsafe { Ok(((*self.internal).get_param_data)(index as i32) as *mut T) }
426    }
427
428    /// 引数をメタテーブルを持つ型付きuserdataとして取得する。
429    ///
430    /// # Note
431    ///
432    /// `T`ではない型から作成されたuserdataを取得しようとした場合は
433    /// [`GetParamError::ConversionError`]を返します。
434    pub fn get_param_userdata<T: AsScriptModuleUserData>(
435        &self,
436        index: usize,
437    ) -> GetParamResult<ScriptModuleUserData<T>, ParamConversionError> {
438        self.assert_param_type(index, ParamType::Userdata)
439            .map_err(GetParamError::into_conversion_error)?;
440        let ptr = unsafe {
441            ((*self.internal).get_param_meta_table)(
442                index as i32,
443                type_to_meta_method_functions::<T>() as _,
444            )
445        };
446        if ptr.is_null() {
447            return Err(GetParamError::ConversionError(ParamConversionError::new(
448                "userdata type mismatch",
449            )));
450        }
451        let arc_ref = unsafe {
452            let boxed = &*(ptr as *const std::sync::Arc<std::sync::Mutex<T>>);
453            boxed.clone()
454        };
455        Ok(ScriptModuleUserData { data: arc_ref })
456    }
457
458    /// 引数をブール値として取得する。
459    pub fn get_param_boolean(&self, index: usize) -> GetParamResult<bool> {
460        self.assert_param_type(index, ParamType::Boolean)?;
461        unsafe { Ok(((*self.internal).get_param_boolean)(index as i32)) }
462    }
463
464    /// 引数のテーブルの要素を整数として取得する。
465    ///
466    /// # Note
467    ///
468    /// 引数を取得できない場合は0を返します。
469    pub fn get_param_table_int(
470        &self,
471        index: usize,
472        key: &str,
473    ) -> ScriptModuleCallHandleResult<i32> {
474        self.assert_param_type_for_call(index, ParamType::Table)?;
475        let c_key = std::ffi::CString::new(key)
476            .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
477        Ok(unsafe { ((*self.internal).get_param_table_int)(index as i32, c_key.as_ptr()) })
478    }
479
480    /// 引数のテーブルの要素を整数として取得し、指定された型に変換する。
481    pub fn get_param_table_integer<T>(
482        &self,
483        index: usize,
484        key: &str,
485    ) -> ScriptModuleCallHandleResult<T, T::Error>
486    where
487        T: FromScriptModuleInteger,
488    {
489        let value = self
490            .get_param_table_int(index, key)
491            .map_err(ScriptModuleCallHandleError::into_conversion_error)?;
492        convert_script_module_integer(value)
493    }
494
495    /// 引数のテーブルの要素を浮動小数点数として取得する。
496    ///
497    /// # Note
498    ///
499    /// 引数を取得できない場合は0.0を返します。
500    pub fn get_param_table_float(
501        &self,
502        index: usize,
503        key: &str,
504    ) -> ScriptModuleCallHandleResult<f64> {
505        self.assert_param_type_for_call(index, ParamType::Table)?;
506        let c_key = std::ffi::CString::new(key)
507            .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
508        Ok(unsafe { ((*self.internal).get_param_table_double)(index as i32, c_key.as_ptr()) })
509    }
510
511    /// 引数のテーブルの要素を文字列として取得する。
512    pub fn get_param_table_str(
513        &self,
514        index: usize,
515        key: &str,
516    ) -> ScriptModuleCallHandleResult<Option<String>> {
517        self.assert_param_type_for_call(index, ParamType::Table)?;
518        let c_key = std::ffi::CString::new(key)
519            .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
520        unsafe {
521            let c_str = ((*self.internal).get_param_table_string)(index as i32, c_key.as_ptr());
522            Ok(if c_str.is_null() {
523                None
524            } else {
525                Some(
526                    std::ffi::CStr::from_ptr(c_str)
527                        .to_string_lossy()
528                        .into_owned(),
529                )
530            })
531        }
532    }
533
534    /// 引数のテーブルの要素をブール値として取得する。
535    ///
536    /// # Note
537    ///
538    /// 引数を取得できない場合は`false`を返します。
539    pub fn get_param_table_boolean(
540        &self,
541        index: usize,
542        key: &str,
543    ) -> ScriptModuleCallHandleResult<bool> {
544        self.assert_param_type_for_call(index, ParamType::Table)?;
545        let c_key = std::ffi::CString::new(key)
546            .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
547        Ok(unsafe { ((*self.internal).get_param_table_boolean)(index as i32, c_key.as_ptr()) })
548    }
549
550    /// 引数の配列の要素の数を取得する。
551    pub fn get_param_array_len(&self, index: usize) -> usize {
552        unsafe { ((*self.internal).get_param_array_num)(index as i32) as usize }
553    }
554
555    /// 引数の配列の要素を数値として取得する。
556    pub fn get_param_array_int(&self, index: usize, array_index: usize) -> i32 {
557        unsafe { ((*self.internal).get_param_array_int)(index as i32, array_index as i32) }
558    }
559
560    /// 引数の配列の要素を浮動小数点数として取得する。
561    pub fn get_param_array_float(&self, index: usize, array_index: usize) -> f64 {
562        unsafe { ((*self.internal).get_param_array_double)(index as i32, array_index as i32) }
563    }
564
565    /// 引数の配列の要素を文字列として取得する。
566    pub fn get_param_array_str(&self, index: usize, array_index: usize) -> Option<String> {
567        unsafe {
568            let c_str = ((*self.internal).get_param_array_string)(index as i32, array_index as i32);
569            if c_str.is_null() {
570                None
571            } else {
572                Some(
573                    std::ffi::CStr::from_ptr(c_str)
574                        .to_string_lossy()
575                        .into_owned(),
576                )
577            }
578        }
579    }
580
581    /// 関数のエラーを設定する。
582    pub fn set_error(&mut self, message: &str) -> ScriptModuleCallHandleResult<()> {
583        let c_message = std::ffi::CString::new(message)
584            .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
585        unsafe {
586            ((*self.internal).set_error)(c_message.as_ptr());
587        }
588        Ok(())
589    }
590
591    /// 関数の返り値を追加する。
592    pub fn push_result<T: IntoScriptModuleReturnValue>(
593        &mut self,
594        value: T,
595    ) -> Result<(), IntoScriptModuleReturnValueError<T::Err>> {
596        value.push_into(self)
597    }
598
599    /// 関数の返り値に整数を追加する。
600    pub fn push_result_int(&mut self, value: i32) {
601        unsafe {
602            ((*self.internal).push_result_int)(value);
603        }
604    }
605
606    /// 関数の返り値に浮動小数点数を追加する。
607    pub fn push_result_float(&mut self, value: f64) {
608        unsafe {
609            ((*self.internal).push_result_double)(value);
610        }
611    }
612
613    /// 関数の返り値に文字列を追加する。
614    pub fn push_result_str(&mut self, value: &str) -> ScriptModuleCallHandleResult<()> {
615        let c_value = std::ffi::CString::new(value)
616            .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
617        unsafe {
618            ((*self.internal).push_result_string)(c_value.as_ptr());
619        }
620        Ok(())
621    }
622
623    /// 関数の返り値にデータポインタを追加する。
624    pub fn push_result_data<T>(&mut self, value: *const T) {
625        unsafe {
626            ((*self.internal).push_result_data)(value as *const std::ffi::c_void);
627        }
628    }
629
630    /// 関数の返り値に関数を追加する。
631    ///
632    /// # Note
633    ///
634    /// メモリリークします。
635    pub fn push_result_function(&mut self, callback: ScriptModuleFunctionCallback) {
636        unsafe {
637            ((*self.internal).push_result_function)(callback.func, callback.userdata);
638        }
639    }
640
641    /// 関数の返り値にメタテーブルを追加する。
642    pub fn push_result_meta_table<T: Into<ErasedScriptModuleUserData>>(&mut self, meta_table: T) {
643        unsafe {
644            let meta_table: ErasedScriptModuleUserData = meta_table.into();
645            ((*self.internal).push_result_meta_table)(
646                meta_table.meta_method_functions,
647                meta_table.userdata,
648            );
649        }
650    }
651
652    /// 関数の返り値に整数の連想配列を追加する。
653    pub fn push_result_table_int<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
654    where
655        T: std::iter::IntoIterator<Item = (&'a str, i32)>,
656    {
657        let mut keys = Vec::new();
658        let mut values = Vec::new();
659        for (key, value) in table {
660            let c_key = std::ffi::CString::new(key)
661                .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
662            keys.push(c_key);
663            values.push(value);
664        }
665        let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
666        unsafe {
667            ((*self.internal).push_result_table_int)(
668                key_ptrs.as_ptr(),
669                values.as_ptr(),
670                key_ptrs.len() as i32,
671            );
672        }
673        Ok(())
674    }
675
676    /// 関数の返り値に浮動小数点数の連想配列を追加する。
677    pub fn push_result_table_float<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
678    where
679        T: std::iter::IntoIterator<Item = (&'a str, f64)>,
680    {
681        let mut keys = Vec::new();
682        let mut values = Vec::new();
683        for (key, value) in table {
684            let c_key = std::ffi::CString::new(key)
685                .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
686            keys.push(c_key);
687            values.push(value);
688        }
689        let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
690        unsafe {
691            ((*self.internal).push_result_table_double)(
692                key_ptrs.as_ptr(),
693                values.as_ptr(),
694                key_ptrs.len() as i32,
695            );
696        }
697        Ok(())
698    }
699
700    /// 関数の返り値に文字列の連想配列を追加する。
701    pub fn push_result_table_str<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
702    where
703        T: std::iter::IntoIterator<Item = (&'a str, &'a str)>,
704    {
705        let mut keys = Vec::new();
706        let mut values = Vec::new();
707        for (key, value) in table {
708            let c_key = std::ffi::CString::new(key)
709                .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
710            let c_value = std::ffi::CString::new(value)
711                .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
712            keys.push(c_key);
713            values.push(c_value);
714        }
715        if keys.len() > i32::MAX as usize {
716            return Err(ScriptModuleCallHandleError::TooManyElements);
717        }
718        let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
719        let value_ptrs: Vec<*const std::os::raw::c_char> =
720            values.iter().map(|v| v.as_ptr()).collect();
721        unsafe {
722            ((*self.internal).push_result_table_string)(
723                key_ptrs.as_ptr(),
724                value_ptrs.as_ptr(),
725                key_ptrs.len() as i32,
726            );
727        }
728        Ok(())
729    }
730
731    /// 関数の返り値にブール値の連想配列を追加する。
732    pub fn push_result_table_boolean<'a, T>(&mut self, table: T) -> ScriptModuleCallHandleResult<()>
733    where
734        T: std::iter::IntoIterator<Item = (&'a str, bool)>,
735    {
736        let mut keys = Vec::new();
737        let mut values = Vec::new();
738        for (key, value) in table {
739            let c_key = std::ffi::CString::new(key)
740                .map_err(ScriptModuleCallHandleError::KeyContainsNullByte)?;
741            keys.push(c_key);
742            values.push(value);
743        }
744        let key_ptrs: Vec<*const std::os::raw::c_char> = keys.iter().map(|k| k.as_ptr()).collect();
745        unsafe {
746            ((*self.internal).push_result_table_boolean)(
747                key_ptrs.as_ptr(),
748                values.as_ptr(),
749                key_ptrs.len() as i32,
750            );
751        }
752        Ok(())
753    }
754
755    /// 関数の返り値に整数の配列を追加する。
756    pub fn push_result_array_int(&mut self, values: &[i32]) -> ScriptModuleCallHandleResult<()> {
757        if values.len() > i32::MAX as usize {
758            return Err(ScriptModuleCallHandleError::TooManyElements);
759        }
760        unsafe {
761            ((*self.internal).push_result_array_int)(values.as_ptr(), values.len() as i32);
762        }
763        Ok(())
764    }
765
766    /// 関数の返り値に浮動小数点数の配列を追加する。
767    pub fn push_result_array_float(&mut self, values: &[f64]) -> ScriptModuleCallHandleResult<()> {
768        if values.len() > i32::MAX as usize {
769            return Err(ScriptModuleCallHandleError::TooManyElements);
770        }
771        unsafe {
772            ((*self.internal).push_result_array_double)(values.as_ptr(), values.len() as i32);
773        }
774        Ok(())
775    }
776
777    /// 関数の返り値に文字列の配列を追加する。
778    pub fn push_result_array_str(&mut self, values: &[&str]) -> ScriptModuleCallHandleResult<()> {
779        let c_values: Vec<std::ffi::CString> = values
780            .iter()
781            .map(|s| std::ffi::CString::new(*s))
782            .collect::<Result<_, _>>()
783            .map_err(ScriptModuleCallHandleError::ValueContainsNullByte)?;
784        if c_values.len() > i32::MAX as usize {
785            return Err(ScriptModuleCallHandleError::TooManyElements);
786        }
787        let c_value_ptrs: Vec<*const std::os::raw::c_char> =
788            c_values.iter().map(|s| s.as_ptr()).collect();
789        unsafe {
790            ((*self.internal).push_result_array_string)(
791                c_value_ptrs.as_ptr(),
792                c_value_ptrs.len() as i32,
793            );
794        }
795        Ok(())
796    }
797
798    /// 関数の返り値にブール値の配列を追加する。
799    pub fn push_result_array_boolean(
800        &mut self,
801        values: &[bool],
802    ) -> ScriptModuleCallHandleResult<()> {
803        if values.len() > i32::MAX as usize {
804            return Err(ScriptModuleCallHandleError::TooManyElements);
805        }
806        unsafe {
807            ((*self.internal).push_result_array_boolean)(values.as_ptr(), values.len() as i32);
808        }
809        Ok(())
810    }
811
812    /// 関数の返り値にブール値を追加する。
813    pub fn push_result_boolean(&mut self, value: bool) {
814        unsafe {
815            ((*self.internal).push_result_boolean)(value);
816        }
817    }
818
819    /// 読み取り専用の編集セクション。
820    pub fn read_section(&self) -> &crate::generic::ReadSection {
821        &self.read_section
822    }
823}
824
825/// スクリプトモジュールの引数として受け取れる値。
826///
827/// # Note
828///
829/// このtraitはDeriveマクロを使用して実装することもできます。
830/// 詳細は[`derive@FromScriptModuleParam`]のドキュメントを参照してください。
831pub trait FromScriptModuleParam<'a>: Sized {
832    type Error: std::error::Error;
833
834    fn from_param(
835        param: &'a crate::module::ScriptModuleCallHandle,
836        index: usize,
837    ) -> GetParamResult<Self, Self::Error>;
838}
839
840pub use aviutl2_macros::FromScriptModuleParam;
841
842impl<'a> FromScriptModuleParam<'a> for &'a crate::generic::ReadSection {
843    type Error = std::convert::Infallible;
844
845    fn from_param(
846        param: &'a crate::module::ScriptModuleCallHandle,
847        _index: usize,
848    ) -> GetParamResult<Self> {
849        Ok(param.read_section())
850    }
851}
852
853impl<'a> FromScriptModuleParam<'a> for i32 {
854    type Error = std::convert::Infallible;
855
856    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
857        param.get_param_int(index)
858    }
859}
860#[duplicate::duplicate_item(
861    Integer Failable;
862    [i8]    [true];
863    [i16]   [true];
864    [i64]   [false];
865    [i128]  [false];
866    [isize] [false];
867    [u8]    [true];
868    [u16]   [true];
869    [u32]   [true];
870    [u64]   [false];
871    [u128]  [false];
872    [usize] [false];
873)]
874impl<'a> FromScriptModuleParam<'a> for Integer {
875    type Error = std::num::TryFromIntError;
876
877    fn from_param(
878        param: &'a ScriptModuleCallHandle,
879        index: usize,
880    ) -> GetParamResult<Self, Self::Error> {
881        let value = param
882            .get_param_int(index)
883            .map_err(GetParamError::into_conversion_error)?;
884        comptime_if::comptime_if!(
885            if failable where (failable = Failable) {
886                value.try_into().map_err(GetParamError::ConversionError)
887            } else {
888                Ok(value as Integer)
889            }
890        )
891    }
892}
893impl<'a> FromScriptModuleParam<'a> for f64 {
894    type Error = std::convert::Infallible;
895
896    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
897        param.get_param_float(index)
898    }
899}
900impl<'a> FromScriptModuleParam<'a> for f32 {
901    type Error = std::convert::Infallible;
902
903    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
904        param.get_param_float(index).map(|value| value as f32)
905    }
906}
907impl<'a> FromScriptModuleParam<'a> for bool {
908    type Error = std::convert::Infallible;
909
910    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
911        param.get_param_boolean(index)
912    }
913}
914impl<'a> FromScriptModuleParam<'a> for String {
915    type Error = std::convert::Infallible;
916
917    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
918        param.get_param_str(index)
919    }
920}
921impl<'a, T> FromScriptModuleParam<'a> for *mut T {
922    type Error = std::convert::Infallible;
923
924    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
925        param.get_param_data(index)
926    }
927}
928impl<'a, T> FromScriptModuleParam<'a> for *const T {
929    type Error = std::convert::Infallible;
930
931    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
932        Ok(param.get_param_data(index)? as _)
933    }
934}
935impl<'a, T> FromScriptModuleParam<'a> for NonNull<T> {
936    type Error = ParamConversionError;
937
938    fn from_param(
939        param: &'a ScriptModuleCallHandle,
940        index: usize,
941    ) -> GetParamResult<Self, Self::Error> {
942        let ptr = param
943            .get_param_data(index)
944            .map_err(GetParamError::into_conversion_error)?;
945        NonNull::new(ptr).ok_or_else(|| {
946            GetParamError::ConversionError(ParamConversionError::new("value is null"))
947        })
948    }
949}
950impl<'a, T: Send + Sync + 'static + AsScriptModuleUserData> FromScriptModuleParam<'a>
951    for ScriptModuleUserData<T>
952{
953    type Error = ParamConversionError;
954
955    fn from_param(
956        param: &'a ScriptModuleCallHandle,
957        index: usize,
958    ) -> GetParamResult<Self, Self::Error> {
959        param.get_param_userdata(index)
960    }
961}
962#[duplicate::duplicate_item(
963    Integer     NonZero        Failable;
964    [i8]        [NonZeroI8]    [true];
965    [i16]       [NonZeroI16]   [true];
966    [i64]       [NonZeroI64]   [false];
967    [i128]      [NonZeroI128]  [false];
968    [isize]     [NonZeroIsize] [false];
969    [u8]        [NonZeroU8]    [true];
970    [u16]       [NonZeroU16]   [true];
971    [u32]       [NonZeroU32]   [true];
972    [u64]       [NonZeroU64]   [false];
973    [u128]      [NonZeroU128]  [false];
974    [usize]     [NonZeroUsize] [false];
975)]
976impl<'a> FromScriptModuleParam<'a> for NonZero {
977    type Error = ParamConversionError;
978
979    fn from_param(
980        param: &'a ScriptModuleCallHandle,
981        index: usize,
982    ) -> GetParamResult<Self, Self::Error> {
983        let value = param
984            .get_param_int(index)
985            .map_err(GetParamError::into_conversion_error)?;
986        let value: Integer = comptime_if::comptime_if!(
987            if failable where (failable = Failable) {
988                value
989                    .try_into()
990                    .map_err(|error: std::num::TryFromIntError| GetParamError::ConversionError(ParamConversionError::new(error.to_string())))?
991            } else {
992                value as Integer
993            }
994        );
995        NonZero::new(value).ok_or_else(|| {
996            GetParamError::ConversionError(ParamConversionError::new("value is zero"))
997        })
998    }
999}
1000impl<'a> FromScriptModuleParam<'a> for NonZeroI32 {
1001    type Error = ParamConversionError;
1002
1003    fn from_param(
1004        param: &'a ScriptModuleCallHandle,
1005        index: usize,
1006    ) -> GetParamResult<Self, Self::Error> {
1007        let value = param
1008            .get_param_int(index)
1009            .map_err(GetParamError::into_conversion_error)?;
1010        NonZeroI32::new(value).ok_or_else(|| {
1011            GetParamError::ConversionError(ParamConversionError::new("value is zero"))
1012        })
1013    }
1014}
1015
1016impl<'a, T> FromScriptModuleParam<'a> for Option<T>
1017where
1018    T: FromScriptModuleParam<'a>,
1019{
1020    type Error = T::Error;
1021
1022    fn from_param(
1023        param: &'a ScriptModuleCallHandle,
1024        index: usize,
1025    ) -> GetParamResult<Self, Self::Error> {
1026        match param.get_param_type(index) {
1027            None | Some(ParamType::Nil) => Ok(None),
1028            Some(_) => T::from_param(param, index).map(Some),
1029        }
1030    }
1031}
1032impl<'a> FromScriptModuleParam<'a> for () {
1033    type Error = std::convert::Infallible;
1034
1035    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
1036        param
1037            .get_param_type(index)
1038            .map(|_| ())
1039            .ok_or(GetParamError::IndexOutOfBounds {
1040                index,
1041                len: param.len(),
1042            })
1043    }
1044}
1045
1046/// スクリプトモジュールの引数として渡される配列。
1047pub struct ScriptModuleParamArray<'a> {
1048    index: usize,
1049    ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
1050    marker: std::marker::PhantomData<&'a ()>,
1051}
1052
1053impl std::fmt::Debug for ScriptModuleParamArray<'_> {
1054    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1055        f.debug_struct("ScriptModuleParamArray")
1056            .field("index", &self.index)
1057            .field("len", &self.len())
1058            .finish()
1059    }
1060}
1061
1062impl<'a> ScriptModuleParamArray<'a> {
1063    /// 配列の長さを返す。
1064    pub fn len(&self) -> usize {
1065        unsafe { ((*self.ptr).get_param_array_num)(self.index as i32) as usize }
1066    }
1067
1068    /// 配列が空かどうかを返す。
1069    pub fn is_empty(&self) -> bool {
1070        self.len() == 0
1071    }
1072
1073    /// 配列の要素を整数として取得する。
1074    pub fn get_int(&self, array_index: usize) -> i32 {
1075        unsafe { ((*self.ptr).get_param_array_int)(self.index as i32, array_index as i32) }
1076    }
1077
1078    /// 配列の要素を浮動小数点数として取得する。
1079    pub fn get_float(&self, array_index: usize) -> f64 {
1080        unsafe { ((*self.ptr).get_param_array_double)(self.index as i32, array_index as i32) }
1081    }
1082
1083    /// 配列の要素を文字列として取得する。
1084    pub fn get_str(&self, array_index: usize) -> Option<String> {
1085        unsafe {
1086            let c_str = ((*self.ptr).get_param_array_string)(self.index as i32, array_index as i32);
1087            if c_str.is_null() {
1088                None
1089            } else {
1090                Some(
1091                    std::ffi::CStr::from_ptr(c_str)
1092                        .to_string_lossy()
1093                        .into_owned(),
1094                )
1095            }
1096        }
1097    }
1098}
1099
1100impl<'a> FromScriptModuleParam<'a> for ScriptModuleParamArray<'a> {
1101    type Error = std::convert::Infallible;
1102
1103    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
1104        param.assert_param_type(index, ParamType::Table)?;
1105        Ok(ScriptModuleParamArray {
1106            index,
1107            ptr: param.internal,
1108            marker: std::marker::PhantomData,
1109        })
1110    }
1111}
1112
1113/// スクリプトモジュールの引数として渡される連想配列。
1114#[derive(Debug)]
1115pub struct ScriptModuleParamTable<'a> {
1116    index: usize,
1117    ptr: *mut aviutl2_sys::module2::SCRIPT_MODULE_PARAM,
1118    marker: std::marker::PhantomData<&'a ()>,
1119}
1120
1121impl<'a> ScriptModuleParamTable<'a> {
1122    /// 連想配列の要素を整数として取得する。
1123    pub fn get_int(&self, key: &str) -> i32 {
1124        let c_key = std::ffi::CString::new(key).unwrap();
1125        unsafe { ((*self.ptr).get_param_table_int)(self.index as i32, c_key.as_ptr()) }
1126    }
1127
1128    /// 連想配列の要素を浮動小数点数として取得する。
1129    pub fn get_float(&self, key: &str) -> f64 {
1130        let c_key = std::ffi::CString::new(key).unwrap();
1131        unsafe { ((*self.ptr).get_param_table_double)(self.index as i32, c_key.as_ptr()) }
1132    }
1133
1134    /// 連想配列の要素を文字列として取得する。
1135    pub fn get_str(&self, key: &str) -> Option<String> {
1136        let c_key = std::ffi::CString::new(key).unwrap();
1137        unsafe {
1138            let c_str = ((*self.ptr).get_param_table_string)(self.index as i32, c_key.as_ptr());
1139            if c_str.is_null() {
1140                None
1141            } else {
1142                Some(
1143                    std::ffi::CStr::from_ptr(c_str)
1144                        .to_string_lossy()
1145                        .into_owned(),
1146                )
1147            }
1148        }
1149    }
1150
1151    /// 連想配列の要素をブール値として取得する。
1152    pub fn get_boolean(&self, key: &str) -> bool {
1153        let c_key = std::ffi::CString::new(key).unwrap();
1154        unsafe { ((*self.ptr).get_param_table_boolean)(self.index as i32, c_key.as_ptr()) }
1155    }
1156}
1157
1158impl<'a> FromScriptModuleParam<'a> for ScriptModuleParamTable<'a> {
1159    type Error = std::convert::Infallible;
1160
1161    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
1162        param.assert_param_type(index, ParamType::Table)?;
1163        Ok(ScriptModuleParamTable {
1164            index,
1165            ptr: param.internal,
1166            marker: std::marker::PhantomData,
1167        })
1168    }
1169}
1170
1171impl<'a> FromScriptModuleParam<'a> for Vec<String> {
1172    type Error = ParamConversionError;
1173
1174    fn from_param(
1175        param: &'a ScriptModuleCallHandle,
1176        index: usize,
1177    ) -> GetParamResult<Self, Self::Error> {
1178        let array = ScriptModuleParamArray::from_param(param, index)
1179            .map_err(GetParamError::into_conversion_error)?;
1180        let mut result = Vec::new();
1181        for i in 0..array.len() {
1182            let value = array.get_str(i).ok_or_else(|| {
1183                GetParamError::ConversionError(ParamConversionError::new(format!(
1184                    "array element #{i} is not a string"
1185                )))
1186            })?;
1187            result.push(value);
1188        }
1189        Ok(result)
1190    }
1191}
1192impl<'a> FromScriptModuleParam<'a> for Vec<i32> {
1193    type Error = std::convert::Infallible;
1194
1195    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
1196        let array = ScriptModuleParamArray::from_param(param, index)?;
1197        let mut result = Vec::new();
1198        for i in 0..array.len() {
1199            result.push(array.get_int(i));
1200        }
1201        Ok(result)
1202    }
1203}
1204#[duplicate::duplicate_item(
1205    Integer Failable;
1206    [i8]    [true];
1207    [i16]   [true];
1208    [i64]   [false];
1209    [i128]  [false];
1210    [isize] [false];
1211    [u8]    [true];
1212    [u16]   [true];
1213    [u32]   [true];
1214    [u64]   [true];
1215    [u128]  [true];
1216    [usize] [true];
1217)]
1218impl<'a> FromScriptModuleParam<'a> for Vec<Integer> {
1219    type Error = std::num::TryFromIntError;
1220
1221    fn from_param(
1222        param: &'a ScriptModuleCallHandle,
1223        index: usize,
1224    ) -> GetParamResult<Self, Self::Error> {
1225        let array = ScriptModuleParamArray::from_param(param, index)
1226            .map_err(GetParamError::into_conversion_error)?;
1227        let mut result = Vec::new();
1228        for i in 0..array.len() {
1229            let value = array.get_int(i);
1230            comptime_if::comptime_if!(
1231                if failable where (failable = Failable) {
1232                    result.push(value.try_into().map_err(GetParamError::ConversionError)?);
1233                } else {
1234                    result.push(value as Integer);
1235                }
1236            );
1237        }
1238        Ok(result)
1239    }
1240}
1241impl<'a> FromScriptModuleParam<'a> for Vec<f64> {
1242    type Error = std::convert::Infallible;
1243
1244    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
1245        let array = ScriptModuleParamArray::from_param(param, index)?;
1246        let mut result = Vec::new();
1247        for i in 0..array.len() {
1248            result.push(array.get_float(i));
1249        }
1250        Ok(result)
1251    }
1252}
1253impl<'a> FromScriptModuleParam<'a> for Vec<f32> {
1254    type Error = std::convert::Infallible;
1255
1256    fn from_param(param: &'a ScriptModuleCallHandle, index: usize) -> GetParamResult<Self> {
1257        let array = ScriptModuleParamArray::from_param(param, index)?;
1258        let mut result = Vec::new();
1259        for i in 0..array.len() {
1260            result.push(array.get_float(i) as f32);
1261        }
1262        Ok(result)
1263    }
1264}
1265
1266/// 連想配列の値として使える型。
1267pub trait FromScriptModuleParamTable<'a>: Sized {
1268    type Error: std::error::Error;
1269
1270    fn from_param_table(
1271        param: &'a crate::module::ScriptModuleParamTable,
1272        key: &str,
1273    ) -> GetParamResult<Self, Self::Error>;
1274}
1275
1276impl<'a> FromScriptModuleParamTable<'a> for i32 {
1277    type Error = std::convert::Infallible;
1278
1279    fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> GetParamResult<Self> {
1280        Ok(param.get_int(key))
1281    }
1282}
1283#[duplicate::duplicate_item(
1284    Integer Failable;
1285    [i8]    [true];
1286    [i16]   [true];
1287    [i64]   [false];
1288    [i128]  [false];
1289    [isize] [false];
1290    [u8]    [true];
1291    [u16]   [true];
1292    [u32]   [true];
1293    [u64]   [false];
1294    [u128]  [false];
1295    [usize] [false];
1296)]
1297impl<'a> FromScriptModuleParamTable<'a> for Integer {
1298    type Error = std::num::TryFromIntError;
1299
1300    fn from_param_table(
1301        param: &'a ScriptModuleParamTable,
1302        key: &str,
1303    ) -> GetParamResult<Self, Self::Error> {
1304        let value = param.get_int(key);
1305        comptime_if::comptime_if!(
1306            if failable where (failable = Failable) {
1307                value.try_into().map_err(GetParamError::ConversionError)
1308            } else {
1309                Ok(value as Integer)
1310            }
1311        )
1312    }
1313}
1314impl<'a> FromScriptModuleParamTable<'a> for f64 {
1315    type Error = std::convert::Infallible;
1316
1317    fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> GetParamResult<Self> {
1318        Ok(param.get_float(key))
1319    }
1320}
1321impl<'a> FromScriptModuleParamTable<'a> for f32 {
1322    type Error = std::convert::Infallible;
1323
1324    fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> GetParamResult<Self> {
1325        Ok(param.get_float(key) as f32)
1326    }
1327}
1328impl<'a> FromScriptModuleParamTable<'a> for String {
1329    type Error = ParamConversionError;
1330
1331    fn from_param_table(
1332        param: &'a ScriptModuleParamTable,
1333        key: &str,
1334    ) -> GetParamResult<Self, Self::Error> {
1335        param.get_str(key).ok_or_else(|| {
1336            GetParamError::ConversionError(ParamConversionError::new(format!(
1337                "key `{key}` is not a string"
1338            )))
1339        })
1340    }
1341}
1342impl<'a> FromScriptModuleParamTable<'a> for bool {
1343    type Error = std::convert::Infallible;
1344
1345    fn from_param_table(param: &'a ScriptModuleParamTable, key: &str) -> GetParamResult<Self> {
1346        Ok(param.get_boolean(key))
1347    }
1348}
1349impl<'a, T: FromScriptModuleParamTable<'a>> FromScriptModuleParamTable<'a> for Option<T> {
1350    type Error = T::Error;
1351
1352    fn from_param_table(
1353        param: &'a ScriptModuleParamTable,
1354        key: &str,
1355    ) -> GetParamResult<Self, Self::Error> {
1356        match T::from_param_table(param, key) {
1357            Ok(value) => Ok(Some(value)),
1358            Err(GetParamError::ConversionError(_)) => Ok(None),
1359            Err(error) => Err(error),
1360        }
1361    }
1362}
1363
1364/// スクリプトモジュールの関数の戻り値の型を表す列挙型。
1365#[derive(Debug)]
1366pub enum ScriptModuleReturnValue {
1367    Int(i32),
1368    Float(f64),
1369    String(String),
1370    Boolean(bool),
1371    Data(*const std::ffi::c_void),
1372    StringArray(Vec<String>),
1373    IntArray(Vec<i32>),
1374    FloatArray(Vec<f64>),
1375    IntTable(std::collections::HashMap<String, i32>),
1376    FloatTable(std::collections::HashMap<String, f64>),
1377    StringTable(std::collections::HashMap<String, String>),
1378    Function(ScriptModuleFunctionCallback),
1379    MetaTable(ErasedScriptModuleUserData),
1380}
1381
1382/// [`IntoScriptModuleReturnValue::push_into`]で使われるエラー。
1383#[derive(thiserror::Error, Debug)]
1384pub enum IntoScriptModuleReturnValueError<T> {
1385    #[error("failed to convert value: {0}")]
1386    ConversionFailed(#[source] T),
1387    #[error("failed to push return value: {0}")]
1388    PushFailed(#[from] ScriptModuleCallHandleError),
1389}
1390
1391/// 関数の戻り値として使える型。
1392///
1393/// # Note
1394///
1395/// この関数はDeriveマクロを使用して実装することもできます。
1396/// 詳細は[`derive@IntoScriptModuleReturnValue`]のドキュメントを参照してください。
1397pub trait IntoScriptModuleReturnValue
1398where
1399    Self: Sized,
1400{
1401    type Err: Send + Sync + 'static + Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
1402
1403    fn into_return_values(self) -> Result<Vec<crate::module::ScriptModuleReturnValue>, Self::Err>;
1404    fn push_into(
1405        self,
1406        param: &mut crate::module::ScriptModuleCallHandle,
1407    ) -> Result<(), crate::module::IntoScriptModuleReturnValueError<Self::Err>> {
1408        for value in self
1409            .into_return_values()
1410            .map_err(IntoScriptModuleReturnValueError::ConversionFailed)?
1411        {
1412            match value {
1413                ScriptModuleReturnValue::Int(v) => {
1414                    param.push_result_int(v);
1415                }
1416                ScriptModuleReturnValue::Float(v) => {
1417                    param.push_result_float(v);
1418                }
1419                ScriptModuleReturnValue::String(v) => {
1420                    param.push_result_str(&v)?;
1421                }
1422                ScriptModuleReturnValue::Boolean(v) => {
1423                    param.push_result_boolean(v);
1424                }
1425                ScriptModuleReturnValue::Data(v) => {
1426                    param.push_result_data(v);
1427                }
1428                ScriptModuleReturnValue::Function(v) => {
1429                    param.push_result_function(v);
1430                }
1431                ScriptModuleReturnValue::MetaTable(v) => {
1432                    param.push_result_meta_table(v);
1433                }
1434                ScriptModuleReturnValue::StringArray(v) => {
1435                    let strs: Vec<&str> = v.iter().map(|s| s.as_str()).collect();
1436                    param.push_result_array_str(&strs)?
1437                }
1438                ScriptModuleReturnValue::IntArray(v) => param.push_result_array_int(&v)?,
1439                ScriptModuleReturnValue::FloatArray(v) => param.push_result_array_float(&v)?,
1440                ScriptModuleReturnValue::IntTable(v) => {
1441                    let table = v.iter().map(|(k, v)| (k.as_str(), *v));
1442                    param.push_result_table_int(table)?;
1443                }
1444                ScriptModuleReturnValue::FloatTable(v) => {
1445                    let table = v.iter().map(|(k, v)| (k.as_str(), *v));
1446                    param.push_result_table_float(table)?;
1447                }
1448                ScriptModuleReturnValue::StringTable(v) => {
1449                    let table = v.iter().map(|(k, v)| (k.as_str(), v.as_str()));
1450                    param.push_result_table_str(table)?;
1451                }
1452            };
1453        }
1454        Ok(())
1455    }
1456}
1457pub use aviutl2_macros::IntoScriptModuleReturnValue;
1458
1459impl<T> IntoScriptModuleReturnValue for *const T {
1460    type Err = std::convert::Infallible;
1461
1462    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1463        Ok(vec![ScriptModuleReturnValue::Data(
1464            self as *const std::ffi::c_void,
1465        )])
1466    }
1467}
1468
1469impl IntoScriptModuleReturnValue for ScriptModuleFunctionCallback {
1470    type Err = std::convert::Infallible;
1471
1472    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1473        Ok(vec![ScriptModuleReturnValue::Function(self)])
1474    }
1475}
1476
1477impl<T: Into<ErasedScriptModuleUserData>> IntoScriptModuleReturnValue for T {
1478    type Err = std::convert::Infallible;
1479
1480    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1481        Ok(vec![ScriptModuleReturnValue::MetaTable(self.into())])
1482    }
1483}
1484
1485impl IntoScriptModuleReturnValue for i32 {
1486    type Err = std::convert::Infallible;
1487
1488    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1489        Ok(vec![ScriptModuleReturnValue::Int(self)])
1490    }
1491}
1492#[duplicate::duplicate_item(
1493    Integer;
1494    [i8];
1495    [i16];
1496    [u8];
1497    [u16];
1498)]
1499impl IntoScriptModuleReturnValue for Integer {
1500    type Err = std::convert::Infallible;
1501
1502    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1503        Ok(vec![ScriptModuleReturnValue::Int(self as i32)])
1504    }
1505}
1506#[duplicate::duplicate_item(
1507    Integer;
1508    [i64];
1509    [i128];
1510    [isize];
1511    [u32];
1512    [u64];
1513    [u128];
1514    [usize];
1515)]
1516impl IntoScriptModuleReturnValue for Integer {
1517    type Err = std::num::TryFromIntError;
1518
1519    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1520        Ok(vec![ScriptModuleReturnValue::Int(self.try_into()?)])
1521    }
1522}
1523impl IntoScriptModuleReturnValue for f64 {
1524    type Err = std::convert::Infallible;
1525    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1526        Ok(vec![ScriptModuleReturnValue::Float(self)])
1527    }
1528}
1529impl IntoScriptModuleReturnValue for f32 {
1530    type Err = std::convert::Infallible;
1531    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1532        Ok(vec![ScriptModuleReturnValue::Float(self as f64)])
1533    }
1534}
1535impl IntoScriptModuleReturnValue for bool {
1536    type Err = std::convert::Infallible;
1537    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1538        Ok(vec![ScriptModuleReturnValue::Boolean(self)])
1539    }
1540}
1541impl IntoScriptModuleReturnValue for &str {
1542    type Err = std::convert::Infallible;
1543    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1544        Ok(vec![ScriptModuleReturnValue::String(self.to_string())])
1545    }
1546}
1547impl IntoScriptModuleReturnValue for String {
1548    type Err = std::convert::Infallible;
1549    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1550        Ok(vec![ScriptModuleReturnValue::String(self)])
1551    }
1552}
1553
1554impl IntoScriptModuleReturnValue for ScriptModuleReturnValue {
1555    type Err = std::convert::Infallible;
1556    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1557        Ok(vec![self])
1558    }
1559}
1560
1561impl IntoScriptModuleReturnValue for Vec<ScriptModuleReturnValue> {
1562    type Err = std::convert::Infallible;
1563
1564    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1565        Ok(self)
1566    }
1567}
1568
1569impl<T: IntoScriptModuleReturnValue> IntoScriptModuleReturnValue for Option<T> {
1570    type Err = T::Err;
1571    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1572        if let Some(value) = self {
1573            value.into_return_values()
1574        } else {
1575            Ok(Vec::new())
1576        }
1577    }
1578}
1579impl<T, const N: usize> IntoScriptModuleReturnValue for [T; N]
1580where
1581    Vec<T>: IntoScriptModuleReturnValue,
1582{
1583    type Err = <Vec<T> as IntoScriptModuleReturnValue>::Err;
1584
1585    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1586        let vec: Vec<T> = self.into();
1587        vec.into_return_values()
1588    }
1589}
1590impl<T: IntoScriptModuleReturnValue, E> IntoScriptModuleReturnValue for Result<T, E>
1591where
1592    E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
1593{
1594    type Err = T::Err;
1595
1596    fn into_return_values(
1597        self,
1598    ) -> Result<
1599        Vec<ScriptModuleReturnValue>,
1600        <std::result::Result<T, E> as IntoScriptModuleReturnValue>::Err,
1601    > {
1602        match self {
1603            Ok(value) => value.into_return_values(),
1604            Err(_) => Ok(Vec::new()),
1605        }
1606    }
1607    fn push_into(
1608        self,
1609        param: &mut ScriptModuleCallHandle,
1610    ) -> Result<
1611        (),
1612        IntoScriptModuleReturnValueError<
1613            <std::result::Result<T, E> as IntoScriptModuleReturnValue>::Err,
1614        >,
1615    > {
1616        match self {
1617            Ok(value) => value.push_into(param)?,
1618            Err(err) => {
1619                let e: Box<dyn std::error::Error + 'static> = err.into();
1620                let e = e.to_string();
1621                param.set_error(&e)?
1622            }
1623        }
1624        Ok(())
1625    }
1626}
1627
1628impl IntoScriptModuleReturnValue for () {
1629    type Err = std::convert::Infallible;
1630    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1631        Ok(Vec::new())
1632    }
1633}
1634
1635macro_rules! impl_into_script_module_return_value_for_tuple {
1636    ($($name:ident),+) => {
1637        impl<$($name),+> IntoScriptModuleReturnValue for ($($name,)+)
1638        where
1639            $($name: IntoScriptModuleReturnValue),+
1640        {
1641            type Err = anyhow::Error;
1642
1643            fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1644                let mut vec = Vec::new();
1645                #[allow(non_snake_case)]
1646                let ($($name,)+) = self;
1647                $(
1648                    vec.extend(
1649                        $name.into_return_values()
1650                            .map_err(|e| anyhow::Error::from_boxed(e.into()))?
1651                    );
1652                )+
1653                Ok(vec)
1654            }
1655        }
1656    };
1657}
1658impl_into_script_module_return_value_for_tuple!(T1);
1659impl_into_script_module_return_value_for_tuple!(T1, T2);
1660impl_into_script_module_return_value_for_tuple!(T1, T2, T3);
1661impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4);
1662impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5);
1663impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6);
1664impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7);
1665impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
1666impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
1667impl_into_script_module_return_value_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
1668
1669impl IntoScriptModuleReturnValue for Vec<String> {
1670    type Err = std::convert::Infallible;
1671    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1672        Ok(vec![ScriptModuleReturnValue::StringArray(self)])
1673    }
1674}
1675impl IntoScriptModuleReturnValue for Vec<&str> {
1676    type Err = std::convert::Infallible;
1677    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1678        Ok(vec![ScriptModuleReturnValue::StringArray(
1679            self.iter().map(|s| s.to_string()).collect(),
1680        )])
1681    }
1682}
1683impl IntoScriptModuleReturnValue for Vec<i32> {
1684    type Err = std::convert::Infallible;
1685    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1686        Ok(vec![ScriptModuleReturnValue::IntArray(self)])
1687    }
1688}
1689#[duplicate::duplicate_item(
1690    Integer;
1691    [i8];
1692    [i16];
1693    [u8];
1694    [u16];
1695)]
1696impl IntoScriptModuleReturnValue for Vec<Integer> {
1697    type Err = std::convert::Infallible;
1698    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1699        Ok(vec![ScriptModuleReturnValue::IntArray(
1700            self.into_iter().map(|value| value as i32).collect(),
1701        )])
1702    }
1703}
1704#[duplicate::duplicate_item(
1705    Integer;
1706    [i64];
1707    [i128];
1708    [isize];
1709    [u32];
1710    [u64];
1711    [u128];
1712    [usize];
1713)]
1714impl IntoScriptModuleReturnValue for Vec<Integer> {
1715    type Err = std::num::TryFromIntError;
1716    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1717        Ok(vec![ScriptModuleReturnValue::IntArray(
1718            self.into_iter()
1719                .map(i32::try_from)
1720                .collect::<Result<_, _>>()?,
1721        )])
1722    }
1723}
1724impl IntoScriptModuleReturnValue for Vec<f64> {
1725    type Err = std::convert::Infallible;
1726    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1727        Ok(vec![ScriptModuleReturnValue::FloatArray(self)])
1728    }
1729}
1730impl IntoScriptModuleReturnValue for Vec<f32> {
1731    type Err = std::convert::Infallible;
1732    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1733        Ok(vec![ScriptModuleReturnValue::FloatArray(
1734            self.into_iter().map(f64::from).collect(),
1735        )])
1736    }
1737}
1738impl<T> IntoScriptModuleReturnValue for &[T]
1739where
1740    Vec<T>: IntoScriptModuleReturnValue,
1741    T: Clone,
1742{
1743    type Err = <Vec<T> as IntoScriptModuleReturnValue>::Err;
1744    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1745        let vec: Vec<T> = self.to_vec();
1746        vec.into_return_values()
1747    }
1748}
1749
1750impl IntoScriptModuleReturnValue for std::collections::HashMap<String, i32> {
1751    type Err = std::convert::Infallible;
1752    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1753        Ok(vec![ScriptModuleReturnValue::IntTable(self)])
1754    }
1755}
1756#[duplicate::duplicate_item(
1757    Integer;
1758    [i8];
1759    [i16];
1760    [u8];
1761    [u16];
1762)]
1763impl IntoScriptModuleReturnValue for std::collections::HashMap<String, Integer> {
1764    type Err = std::convert::Infallible;
1765    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1766        Ok(vec![ScriptModuleReturnValue::IntTable(
1767            self.into_iter()
1768                .map(|(key, value)| (key, value as i32))
1769                .collect(),
1770        )])
1771    }
1772}
1773#[duplicate::duplicate_item(
1774    Integer;
1775    [i64];
1776    [i128];
1777    [isize];
1778    [u32];
1779    [u64];
1780    [u128];
1781    [usize];
1782)]
1783impl IntoScriptModuleReturnValue for std::collections::HashMap<String, Integer> {
1784    type Err = std::num::TryFromIntError;
1785    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1786        Ok(vec![ScriptModuleReturnValue::IntTable(
1787            self.into_iter()
1788                .map(|(key, value)| Ok((key, value.try_into()?)))
1789                .collect::<Result<_, Self::Err>>()?,
1790        )])
1791    }
1792}
1793impl IntoScriptModuleReturnValue for std::collections::HashMap<String, f64> {
1794    type Err = std::convert::Infallible;
1795    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1796        Ok(vec![ScriptModuleReturnValue::FloatTable(self)])
1797    }
1798}
1799impl IntoScriptModuleReturnValue for std::collections::HashMap<String, f32> {
1800    type Err = std::convert::Infallible;
1801    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1802        Ok(vec![ScriptModuleReturnValue::FloatTable(
1803            self.into_iter()
1804                .map(|(key, value)| (key, f64::from(value)))
1805                .collect(),
1806        )])
1807    }
1808}
1809impl IntoScriptModuleReturnValue for std::collections::HashMap<String, String> {
1810    type Err = std::convert::Infallible;
1811    fn into_return_values(self) -> Result<Vec<ScriptModuleReturnValue>, Self::Err> {
1812        Ok(vec![ScriptModuleReturnValue::StringTable(self)])
1813    }
1814}
1815
1816#[doc(hidden)]
1817pub mod __table_converter {
1818    pub trait ToOptionalTableEntry {
1819        type Value;
1820        fn to_optional(&self) -> Option<Self::Value>;
1821    }
1822
1823    impl<T: Clone> ToOptionalTableEntry for Option<T> {
1824        type Value = T;
1825        fn to_optional(&self) -> Option<Self::Value> {
1826            self.clone()
1827        }
1828    }
1829    #[duplicate::duplicate_item(
1830        Number;
1831        [i8];
1832        [i16];
1833        [i32];
1834        [i64];
1835        [i128];
1836        [isize];
1837        [u8];
1838        [u16];
1839        [u32];
1840        [u64];
1841        [u128];
1842        [usize];
1843        [f32];
1844        [f64];
1845    )]
1846    impl ToOptionalTableEntry for Number {
1847        type Value = Number;
1848        fn to_optional(&self) -> Option<Self::Value> {
1849            Some(*self)
1850        }
1851    }
1852    impl ToOptionalTableEntry for String {
1853        type Value = String;
1854        fn to_optional(&self) -> Option<Self::Value> {
1855            Some(self.clone())
1856        }
1857    }
1858}
1859
1860#[doc(hidden)]
1861pub fn __push_return_value<T>(param: &mut crate::module::ScriptModuleCallHandle, value: T)
1862where
1863    T: crate::module::IntoScriptModuleReturnValue,
1864{
1865    let res = value.push_into(param);
1866    let _ = res
1867        .map_err(|e| -> Box<dyn std::error::Error + Send + Sync + 'static> {
1868            match e {
1869                crate::module::IntoScriptModuleReturnValueError::PushFailed(e) => Box::new(e),
1870                crate::module::IntoScriptModuleReturnValueError::ConversionFailed(e) => e.into(),
1871            }
1872        })
1873        .push_into(param);
1874}
1875
1876#[cfg(test)]
1877mod tests {
1878    use super::*;
1879
1880    fn assert_from_param<T>()
1881    where
1882        for<'a> T: FromScriptModuleParam<'a>,
1883    {
1884    }
1885
1886    fn assert_into_return_value<T: IntoScriptModuleReturnValue>() {}
1887
1888    fn assert_table_entry<T: __table_converter::ToOptionalTableEntry>() {}
1889
1890    fn assert_zero_is_convertible<T>()
1891    where
1892        T: FromScriptModuleInteger,
1893    {
1894        assert!(convert_script_module_integer::<T>(0).is_ok());
1895    }
1896
1897    #[test]
1898    fn converts_table_integer_to_all_numeric_types() {
1899        assert_zero_is_convertible::<i8>();
1900        assert_zero_is_convertible::<i16>();
1901        assert_zero_is_convertible::<i32>();
1902        assert_zero_is_convertible::<i64>();
1903        assert_zero_is_convertible::<i128>();
1904        assert_zero_is_convertible::<isize>();
1905        assert_zero_is_convertible::<u8>();
1906        assert_zero_is_convertible::<u16>();
1907        assert_zero_is_convertible::<u32>();
1908        assert_zero_is_convertible::<u64>();
1909        assert_zero_is_convertible::<u128>();
1910        assert_zero_is_convertible::<usize>();
1911    }
1912
1913    #[test]
1914    fn implements_numeric_collection_traits() {
1915        macro_rules! assert_integer_traits {
1916            ($($integer:ty),+ $(,)?) => {
1917                $(
1918                    assert_from_param::<Vec<$integer>>();
1919                    assert_into_return_value::<Vec<$integer>>();
1920                    assert_into_return_value::<std::collections::HashMap<String, $integer>>();
1921                    assert_table_entry::<$integer>();
1922                )+
1923            };
1924        }
1925
1926        assert_integer_traits!(
1927            i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
1928        );
1929        assert_from_param::<Vec<f32>>();
1930        assert_from_param::<Vec<f64>>();
1931        assert_into_return_value::<Vec<f32>>();
1932        assert_into_return_value::<Vec<f64>>();
1933        assert_into_return_value::<std::collections::HashMap<String, f32>>();
1934        assert_into_return_value::<std::collections::HashMap<String, f64>>();
1935        assert_table_entry::<f32>();
1936        assert_table_entry::<f64>();
1937    }
1938
1939    #[test]
1940    fn converts_numeric_collections_to_internal_types() {
1941        let values = Vec::<u16>::from([0, u16::MAX])
1942            .into_return_values()
1943            .unwrap();
1944        assert!(matches!(
1945            values.as_slice(),
1946            [ScriptModuleReturnValue::IntArray(values)]
1947                if values == &vec![0, u16::MAX as i32]
1948        ));
1949
1950        let values = Vec::<f32>::from([1.5, -2.25]).into_return_values().unwrap();
1951        assert!(matches!(
1952            values.as_slice(),
1953            [ScriptModuleReturnValue::FloatArray(values)]
1954                if values == &vec![1.5, -2.25]
1955        ));
1956
1957        let values = std::collections::HashMap::from([("value".to_string(), 1.5_f32)])
1958            .into_return_values()
1959            .unwrap();
1960        assert!(matches!(
1961            values.as_slice(),
1962            [ScriptModuleReturnValue::FloatTable(values)]
1963                if values.get("value") == Some(&1.5)
1964        ));
1965    }
1966
1967    #[test]
1968    fn reports_numeric_collection_conversion_errors() {
1969        assert!(
1970            Vec::from([i64::from(i32::MAX) + 1])
1971                .into_return_values()
1972                .is_err()
1973        );
1974        assert!(
1975            std::collections::HashMap::from([("value".to_string(), u64::MAX)])
1976                .into_return_values()
1977                .is_err()
1978        );
1979    }
1980
1981    #[test]
1982    fn reports_table_integer_conversion_errors() {
1983        assert!(matches!(
1984            convert_script_module_integer::<i8>(i8::MAX as i32 + 1),
1985            Err(ScriptModuleCallHandleError::ConversionError(_))
1986        ));
1987        assert!(matches!(
1988            convert_script_module_integer::<u32>(-1),
1989            Err(ScriptModuleCallHandleError::ConversionError(_))
1990        ));
1991    }
1992
1993    #[test]
1994    fn preserves_existing_error_when_changing_conversion_error_type() {
1995        let error: ScriptModuleCallHandleError<ParamConversionError> =
1996            ScriptModuleCallHandleError::TypeMismatch {
1997                expected: ParamType::Table,
1998                actual: ParamType::Number,
1999            }
2000            .into_conversion_error();
2001
2002        assert!(matches!(
2003            error,
2004            ScriptModuleCallHandleError::TypeMismatch {
2005                expected: ParamType::Table,
2006                actual: ParamType::Number,
2007            }
2008        ));
2009    }
2010}