hyperlight-common 0.17.0

Hyperlight's components common to host and guest.
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 The Hyperlight Authors.

use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;

use super::error::Error;
use super::utils::for_each_tuple;
use crate::flatbuffer_wrappers::function_types::{ParameterType, ParameterValue};

/// This is a marker trait that is used to indicate that a type is a
/// valid Hyperlight parameter type.
///
/// For each parameter type Hyperlight supports in host functions, we
/// provide an implementation for `SupportedParameterType`
pub trait SupportedParameterType: Sized + Clone + Send + Sync + 'static {
    /// The underlying Hyperlight parameter type representing this `SupportedParameterType`
    const TYPE: ParameterType;

    /// Get the underling Hyperlight parameter value representing this
    /// `SupportedParameterType`
    fn into_value(self) -> ParameterValue;
    /// Get the actual inner value of this `SupportedParameterType`
    fn from_value(value: ParameterValue) -> Result<Self, Error>;
}

// We can then implement these traits for each type that Hyperlight supports as a parameter or return type
macro_rules! for_each_param_type {
    ($macro:ident) => {
        $macro!(String, String);
        $macro!(i32, Int);
        $macro!(u32, UInt);
        $macro!(i64, Long);
        $macro!(u64, ULong);
        $macro!(f32, Float);
        $macro!(f64, Double);
        $macro!(bool, Bool);
        $macro!(Vec<u8>, VecBytes);
    };
}

macro_rules! impl_supported_param_type {
    ($type:ty, $enum:ident) => {
        impl SupportedParameterType for $type {
            const TYPE: ParameterType = ParameterType::$enum;

            fn into_value(self) -> ParameterValue {
                ParameterValue::$enum(self)
            }

            fn from_value(value: ParameterValue) -> Result<Self, Error> {
                match value {
                    ParameterValue::$enum(i) => Ok(i),
                    other => Err(Error::ParameterValueConversionFailure(
                        other.clone(),
                        stringify!($type),
                    )),
                }
            }
        }
    };
}

for_each_param_type!(impl_supported_param_type);

/// A trait to describe the tuple of parameters that a host function can take.
pub trait ParameterTuple: Sized + Clone + Send + Sync + 'static {
    /// The number of parameters in the tuple
    const SIZE: usize;

    /// The underlying Hyperlight parameter types representing this tuple of `SupportedParameterType`
    const TYPE: &[ParameterType];

    /// Get the underling Hyperlight parameter value representing this
    /// `SupportedParameterType`
    fn into_value(self) -> Vec<ParameterValue>;

    /// Get the actual inner value of this `SupportedParameterType`
    fn from_value(value: Vec<ParameterValue>) -> Result<Self, Error>;
}

impl<T: SupportedParameterType> ParameterTuple for T {
    const SIZE: usize = 1;

    const TYPE: &[ParameterType] = &[T::TYPE];

    fn into_value(self) -> Vec<ParameterValue> {
        vec![self.into_value()]
    }

    fn from_value(value: Vec<ParameterValue>) -> Result<Self, Error> {
        match <[ParameterValue; 1]>::try_from(value) {
            Ok([val]) => Ok(T::from_value(val)?),
            Err(value) => Err(Error::UnexpectedNoOfArguments(value.len(), 1)),
        }
    }
}

macro_rules! impl_param_tuple {
    ([$N:expr] ($($name:ident: $param:ident),*)) => {
        impl<$($param: SupportedParameterType),*> ParameterTuple for ($($param,)*) {
            const SIZE: usize = $N;

            const TYPE: &[ParameterType] = &[
                $($param::TYPE),*
            ];

            fn into_value(self) -> Vec<ParameterValue> {
                let ($($name,)*) = self;
                vec![$($name.into_value()),*]
            }

            fn from_value(value: Vec<ParameterValue>) -> Result<Self, Error> {
                match <[ParameterValue; $N]>::try_from(value) {
                    Ok([$($name,)*]) => Ok(($($param::from_value($name)?,)*)),
                    Err(value) => Err(Error::UnexpectedNoOfArguments(value.len(), $N))
                }
            }
        }
    };
}

for_each_tuple!(impl_param_tuple);