rune/module/module_raw_function_builder.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use ::rust_alloc::sync::Arc;
use crate::compile::ContextError;
use crate::function_meta::{
Associated, AssociatedFunctionData, FunctionData, FunctionMetaKind, ToInstance,
};
use crate::item::IntoComponent;
use crate::module::ItemFnMut;
use crate::runtime::{FunctionHandler, TypeInfo, TypeOf};
use crate::{Hash, ItemBuf};
use super::Module;
/// Raw function builder as returned by [`Module::raw_function`].
///
/// This allows for building a function regularly with
/// [`ModuleRawFunctionBuilder::build`] or statically associate the function
/// with a type through [`ModuleRawFunctionBuilder::build_associated::<T>`].
#[must_use = "Must call one of the build functions, like `build` or `build_associated`"]
pub struct ModuleRawFunctionBuilder<'a, N> {
pub(super) module: &'a mut Module,
pub(super) name: N,
pub(super) handler: Arc<FunctionHandler>,
}
impl<'a, N> ModuleRawFunctionBuilder<'a, N> {
/// Construct a regular function.
///
/// This register the function as a free function in the module it's
/// associated with, who's full name is the name of the module extended by
/// the name of the function.
///
/// # Examples
///
/// ```
/// use rune::{Any, Module};
/// use rune::runtime::VmResult;
///
/// let mut m = Module::with_item(["module"])?;
/// m.raw_function("floob", |_, _, _, _| VmResult::Ok(())).build()?;
/// # Ok::<_, rune::support::Error>(())
/// ```
#[inline]
pub fn build(self) -> Result<ItemFnMut<'a>, ContextError>
where
N: IntoComponent,
{
let item = ItemBuf::with_item([self.name])?;
self.module
.function_from_meta_kind(FunctionMetaKind::Function(FunctionData::from_raw(
item,
self.handler,
)))
}
/// Construct a function that is associated with `T`.
///
/// This registers the function as an assocaited function, which can only be
/// used through the type `T`.
///
/// # Errors
///
/// This function call will cause an error in [`Context::install`] if the
/// type we're associating it with has not been registered.
///
/// [`Context::install`]: crate::Context::install
///
/// ```
/// use rune::{Any, Module, Context};
///
/// #[derive(Any)]
/// struct Thing;
///
/// let mut m = Module::default();
/// m.function("floob", || ()).build_associated::<Thing>()?;
///
/// let mut c = Context::default();
/// assert!(c.install(m).is_err());
/// # Ok::<_, rune::support::Error>(())
/// ```
///
/// # Examples
///
/// ```
/// use rune::{Any, Module};
/// use rune::runtime::VmResult;
///
/// #[derive(Any)]
/// struct Thing;
///
/// let mut m = Module::default();
/// m.ty::<Thing>()?;
/// m.raw_function("floob", |_, _, _, _| VmResult::Ok(())).build_associated::<Thing>()?;
/// # Ok::<_, rune::support::Error>(())
/// ```
#[inline]
pub fn build_associated<T>(self) -> Result<ItemFnMut<'a>, ContextError>
where
N: ToInstance,
T: TypeOf,
{
let associated = Associated::from_type::<T>(self.name.to_instance()?)?;
self.module
.function_from_meta_kind(FunctionMetaKind::AssociatedFunction(
AssociatedFunctionData::from_raw(associated, self.handler),
))
}
/// Construct a function that is associated with a custom dynamically
/// specified container.
///
/// This registers the function as an assocaited function, which can only be
/// used through the specified type.
///
/// [`Hash`] and [`TypeInfo`] are usually constructed through the [`TypeOf`]
/// trait. But that requires access to a static type, for which you should
/// use [`build_associated`] instead.
///
/// # Errors
///
/// The function call will error if the specified type is not already
/// registered in the module.
///
/// [`Hash`]: crate::Hash
/// [`build_associated`]: super::ModuleFunctionBuilder::build_associated
#[inline]
pub fn build_associated_with(
self,
container: Hash,
container_type_info: TypeInfo,
) -> Result<ItemFnMut<'a>, ContextError>
where
N: ToInstance,
{
let associated = Associated::new(self.name.to_instance()?, container, container_type_info);
self.module
.function_from_meta_kind(FunctionMetaKind::AssociatedFunction(
AssociatedFunctionData::from_raw(associated, self.handler),
))
}
}