hyperlight_host/func/
param_type.rs

1/*
2Copyright 2025  The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterType, ParameterValue};
18use tracing::{Span, instrument};
19
20use super::utils::for_each_tuple;
21use crate::HyperlightError::{ParameterValueConversionFailure, UnexpectedNoOfArguments};
22use crate::{Result, log_then_return};
23
24/// This is a marker trait that is used to indicate that a type is a
25/// valid Hyperlight parameter type.
26///
27/// For each parameter type Hyperlight supports in host functions, we
28/// provide an implementation for `SupportedParameterType`
29pub trait SupportedParameterType: Sized + Clone + Send + Sync + 'static {
30    /// The underlying Hyperlight parameter type representing this `SupportedParameterType`
31    const TYPE: ParameterType;
32
33    /// Get the underling Hyperlight parameter value representing this
34    /// `SupportedParameterType`
35    fn into_value(self) -> ParameterValue;
36    /// Get the actual inner value of this `SupportedParameterType`
37    fn from_value(value: ParameterValue) -> Result<Self>;
38}
39
40// We can then implement these traits for each type that Hyperlight supports as a parameter or return type
41macro_rules! for_each_param_type {
42    ($macro:ident) => {
43        $macro!(String, String);
44        $macro!(i32, Int);
45        $macro!(u32, UInt);
46        $macro!(i64, Long);
47        $macro!(u64, ULong);
48        $macro!(f32, Float);
49        $macro!(f64, Double);
50        $macro!(bool, Bool);
51        $macro!(Vec<u8>, VecBytes);
52    };
53}
54
55macro_rules! impl_supported_param_type {
56    ($type:ty, $enum:ident) => {
57        impl SupportedParameterType for $type {
58            const TYPE: ParameterType = ParameterType::$enum;
59
60            #[instrument(skip_all, parent = Span::current(), level= "Trace")]
61            fn into_value(self) -> ParameterValue {
62                ParameterValue::$enum(self)
63            }
64
65            #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
66            fn from_value(value: ParameterValue) -> Result<Self> {
67                match value {
68                    ParameterValue::$enum(i) => Ok(i),
69                    other => {
70                        log_then_return!(ParameterValueConversionFailure(
71                            other.clone(),
72                            stringify!($type)
73                        ));
74                    }
75                }
76            }
77        }
78    };
79}
80
81for_each_param_type!(impl_supported_param_type);
82
83/// A trait to describe the tuple of parameters that a host function can take.
84pub trait ParameterTuple: Sized + Clone + Send + Sync + 'static {
85    /// The number of parameters in the tuple
86    const SIZE: usize;
87
88    /// The underlying Hyperlight parameter types representing this tuple of `SupportedParameterType`
89    const TYPE: &[ParameterType];
90
91    /// Get the underling Hyperlight parameter value representing this
92    /// `SupportedParameterType`
93    fn into_value(self) -> Vec<ParameterValue>;
94
95    /// Get the actual inner value of this `SupportedParameterType`
96    fn from_value(value: Vec<ParameterValue>) -> Result<Self>;
97}
98
99impl<T: SupportedParameterType> ParameterTuple for T {
100    const SIZE: usize = 1;
101
102    const TYPE: &[ParameterType] = &[T::TYPE];
103
104    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
105    fn into_value(self) -> Vec<ParameterValue> {
106        vec![self.into_value()]
107    }
108
109    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
110    fn from_value(value: Vec<ParameterValue>) -> Result<Self> {
111        match <[ParameterValue; 1]>::try_from(value) {
112            Ok([val]) => Ok(T::from_value(val)?),
113            Err(value) => {
114                log_then_return!(UnexpectedNoOfArguments(value.len(), 1));
115            }
116        }
117    }
118}
119
120macro_rules! impl_param_tuple {
121    ([$N:expr] ($($name:ident: $param:ident),*)) => {
122        impl<$($param: SupportedParameterType),*> ParameterTuple for ($($param,)*) {
123            const SIZE: usize = $N;
124
125            const TYPE: &[ParameterType] = &[
126                $($param::TYPE),*
127            ];
128
129            #[instrument(skip_all, parent = Span::current(), level= "Trace")]
130            fn into_value(self) -> Vec<ParameterValue> {
131                let ($($name,)*) = self;
132                vec![$($name.into_value()),*]
133            }
134
135            #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
136            fn from_value(value: Vec<ParameterValue>) -> Result<Self> {
137                match <[ParameterValue; $N]>::try_from(value) {
138                    Ok([$($name,)*]) => Ok(($($param::from_value($name)?,)*)),
139                    Err(value) => { log_then_return!(UnexpectedNoOfArguments(value.len(), $N)); }
140                }
141            }
142        }
143    };
144}
145
146for_each_tuple!(impl_param_tuple);