tvm_ffi/
function_internal.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19use crate::any::{Any, AnyView, ArgTryFromAnyView};
20use crate::error::Result;
21use crate::string::{Bytes, String};
22use crate::type_traits::AnyCompatible;
23
24//------------------------------------------------------------------------
25// PackedCallable
26//------------------------------------------------------------------------
27pub trait AsPackedCallable<I, O> {
28    // Call the function in packed convention
29    fn call_packed(&self, packed_args: &[AnyView]) -> Result<Any>;
30}
31
32#[inline]
33pub fn call_packed_callable<Fun, I, O>(func: Fun, packed_args: &[AnyView]) -> Result<Any>
34where
35    Fun: AsPackedCallable<I, O>,
36{
37    func.call_packed(packed_args)
38}
39
40macro_rules! impl_as_packed_callable {
41    ($len:literal; $($t:ident),*) => {
42        impl<Fun, $($t,)* Out> AsPackedCallable<($($t,)*), Out> for Fun
43        where
44            Fun: Fn($($t,)*) -> Result<Out> + 'static,
45            Any: From<Out>,
46            $($t: ArgTryFromAnyView),*
47        {
48            fn call_packed(&self, packed_args: &[AnyView]) -> Result<Any>
49            {
50                crate::ensure!(
51                    packed_args.len() == $len, crate::error::VALUE_ERROR,
52                    "Expected {} arguments, got {}", $len, packed_args.len()
53                );
54                // Expand the function call, consuming the iterator.
55                let mut _arg_iter = packed_args.iter().enumerate();
56                let ret_value = self(
57                    $({
58                        // unwrap is safe due to the length check above
59                        let (i, view) = _arg_iter.next().unwrap();
60                        $t::try_from_any_view(view, i)?
61                    }),*
62                )?;
63                Ok(Any::from(ret_value))
64            }
65        }
66    }
67}
68
69impl_as_packed_callable!(0;);
70impl_as_packed_callable!(1; T0);
71impl_as_packed_callable!(2; T0, T1);
72impl_as_packed_callable!(3; T0, T1, T2);
73impl_as_packed_callable!(4; T0, T1, T2, T3);
74impl_as_packed_callable!(5; T0, T1, T2, T3, T4);
75impl_as_packed_callable!(6; T0, T1, T2, T3, T4, T5);
76impl_as_packed_callable!(7; T0, T1, T2, T3, T4, T5, T6);
77impl_as_packed_callable!(8; T0, T1, T2, T3, T4, T5, T6, T7);
78
79//--------------------------------------------------------------
80// IntoArgHolder, helper to convert to canonical holding type
81//
82// This is needed sometimes for reference types that may need to
83// be converted to value types.
84//--------------------------------------------------------------
85pub trait IntoArgHolder {
86    type Target;
87    fn into_arg_holder(self) -> Self::Target;
88}
89
90crate::impl_into_arg_holder_default!(
91    bool, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, String, Bytes
92);
93
94// string will be converted to String for argument passing
95impl IntoArgHolder for &str {
96    type Target = String;
97    fn into_arg_holder(self) -> Self::Target {
98        String::from(self)
99    }
100}
101
102// string will be converted to String for argument passing
103impl IntoArgHolder for &[u8] {
104    type Target = Bytes;
105    fn into_arg_holder(self) -> Self::Target {
106        Bytes::from(self)
107    }
108}
109
110// helper trait to implement IntoArgHolderTuple to apply into_arg_holder to each element
111pub trait IntoArgHolderTuple {
112    type Target;
113    fn into_arg_holder_tuple(self) -> Self::Target;
114}
115
116macro_rules! impl_into_arg_holder_tuple {
117    ( $($T:ident),* ; $($idx:tt),* ) => {
118        impl<$($T),*> $crate::function_internal::IntoArgHolderTuple for ($($T,)*)
119        where
120            $($T: IntoArgHolder),* {
121            type Target = ($($T::Target,)*);
122
123            fn into_arg_holder_tuple(self) -> Self::Target {
124                ($(self.$idx.into_arg_holder(),)*)
125            }
126        }
127    };
128}
129
130impl_into_arg_holder_tuple!(;);
131impl_into_arg_holder_tuple!(T0; 0);
132impl_into_arg_holder_tuple!(T0, T1; 0, 1);
133impl_into_arg_holder_tuple!(T0, T1, T2; 0, 1, 2);
134impl_into_arg_holder_tuple!(T0, T1, T2, T3; 0, 1, 2, 3);
135impl_into_arg_holder_tuple!(T0, T1, T2, T3, T4; 0, 1, 2, 3, 4);
136impl_into_arg_holder_tuple!(T0, T1, T2, T3, T4, T5; 0, 1, 2, 3, 4, 5);
137impl_into_arg_holder_tuple!(T0, T1, T2, T3, T4, T5, T6; 0, 1, 2, 3, 4, 5, 6);
138impl_into_arg_holder_tuple!(T0, T1, T2, T3, T4, T5, T6, T7; 0, 1, 2, 3, 4, 5, 6, 7);
139
140//------------------------------------------------------------
141// ArgIntoRef
142//
143// Helper to turn argument type to reference type
144// This is effectively AsRef<T> but removes the need of T
145//-----------------------------------------------------------
146pub trait ArgIntoRef {
147    type Target;
148    fn to_ref(&self) -> &Self::Target;
149}
150
151crate::impl_arg_into_ref!(
152    bool, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, String, Bytes
153);
154
155//-----------------------------------------------------------
156// TupleAsPackedArgs
157//
158// Helper to turn tuple type to packed arguments
159//-----------------------------------------------------------
160pub trait TupleAsPackedArgs {
161    const LEN: usize;
162    fn fill_any_view<'a>(&'a self, any_view: &mut [AnyView<'a>]);
163}
164
165macro_rules! impl_tuple_as_packed_args {
166    ( $len:expr; $($T:ident),* ; $($idx:tt),* ) => {
167        impl<$($T),*> TupleAsPackedArgs for ($($T,)*)
168        where
169            $(
170                $T: ArgIntoRef,
171                $T::Target: AnyCompatible,
172            )*
173        {
174            const LEN: usize = $len;
175
176            fn fill_any_view<'a>(&'a self, _any_view: &mut [AnyView<'a>]) {
177                $(
178                    _any_view[$idx] = AnyView::from(self.$idx.to_ref());
179                )*
180            }
181        }
182    };
183}
184
185impl_tuple_as_packed_args!(0;;);
186impl_tuple_as_packed_args!(1; T0; 0);
187impl_tuple_as_packed_args!(2; T0, T1; 0, 1);
188impl_tuple_as_packed_args!(3; T0, T1, T2; 0, 1, 2);
189impl_tuple_as_packed_args!(4; T0, T1, T2, T3; 0, 1, 2, 3);
190impl_tuple_as_packed_args!(5; T0, T1, T2, T3, T4; 0, 1, 2, 3, 4);
191impl_tuple_as_packed_args!(6; T0, T1, T2, T3, T4, T5; 0, 1, 2, 3, 4, 5);
192impl_tuple_as_packed_args!(7; T0, T1, T2, T3, T4, T5, T6; 0, 1, 2, 3, 4, 5, 6);
193impl_tuple_as_packed_args!(8; T0, T1, T2, T3, T4, T5, T6, T7; 0, 1, 2, 3, 4, 5, 6, 7);