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
use super::super::{AsContext, AsContextMut, StoreContext, StoreContextMut};
use crate::{store::FuelError, Engine, Extern, Instance};
/// Represents the caller’s context when creating a host function via [`Func::wrap`].
///
/// [`Func::wrap`]: struct.Func.html#method.wrap
pub struct Caller<'a, T> {
ctx: StoreContextMut<'a, T>,
/// The module instance associated to the call.
/// This is `Some` if the host function was called from a Wasm function
/// since all Wasm function are associated to a module instance.
/// This usually is `None` if the host function was called from the host side.
instance: Option<Instance>,
}
impl<'a, T> Caller<'a, T> {
/// Creates a new [`Caller`] from the given store context and [`Instance`] handle.
pub fn new<C>(ctx: &'a mut C, instance: Option<&Instance>) -> Self
where
C: AsContextMut<UserState = T>,
{
Self {
ctx: ctx.as_context_mut(),
instance: instance.copied(),
}
}
/// Queries the caller for an exported definition identifier by `name`.
///
/// Returns `None` if there is no associated [`Instance`] of the caller
/// or if the caller does not provide an export under the name `name`.
pub fn get_export(&self, name: &str) -> Option<Extern> {
self.instance
.and_then(|instance| instance.get_export(self, name))
}
/// Returns a shared reference to the user provided host data.
pub fn data(&self) -> &T {
self.ctx.store.data()
}
/// Returns an exclusive reference to the user provided host data.
pub fn data_mut(&mut self) -> &mut T {
self.ctx.store.data_mut()
}
/// Returns a shared reference to the used [`Engine`].
pub fn engine(&self) -> &Engine {
self.ctx.store.engine()
}
/// Adds `delta` quantity of fuel to the remaining fuel.
///
/// # Panics
///
/// If this overflows the remaining fuel counter.
///
/// # Errors
///
/// If fuel metering is disabled.
pub fn add_fuel(&mut self, delta: u64) -> Result<(), FuelError> {
self.ctx.store.add_fuel(delta)
}
/// Returns the amount of fuel consumed by executions of the [`Store`](crate::Store) so far.
///
/// Returns `None` if fuel metering is disabled.
pub fn fuel_consumed(&self) -> Option<u64> {
self.ctx.store.fuel_consumed()
}
/// Returns the amount of total [`Fuel`] supplied to the [`Store`](crate::Store).
///
/// Returns `None` if fuel metering is disabled.
pub fn fuel_total(&self) -> Option<u64> {
self.ctx.store.fuel_total()
}
/// Synthetically consumes an amount of fuel for the [`Store`](crate::Store).
///
/// Returns the remaining amount of fuel after this operation.
///
/// # Panics
///
/// If this overflows the consumed fuel counter.
///
/// # Errors
///
/// - If fuel metering is disabled.
/// - If more fuel is consumed than available.
pub fn consume_fuel(&mut self, delta: u64) -> Result<u64, FuelError> {
self.ctx.store.consume_fuel(delta)
}
/// Resets the total and consumed amounts of fuel to 0 for the [`Store`](crate::Store).
///
/// # Errors
///
/// - If fuel metering is disabled.
pub fn reset_fuel(&mut self) -> Result<(), FuelError> {
self.ctx.store.reset_fuel()
}
}
impl<T> AsContext for Caller<'_, T> {
type UserState = T;
#[inline]
fn as_context(&self) -> StoreContext<'_, Self::UserState> {
self.ctx.as_context()
}
}
impl<T> AsContextMut for Caller<'_, T> {
#[inline]
fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::UserState> {
self.ctx.as_context_mut()
}
}
impl<'a, T: AsContextMut> From<&'a mut T> for Caller<'a, T::UserState> {
#[inline]
fn from(ctx: &'a mut T) -> Self {
Self {
ctx: ctx.as_context_mut(),
instance: None,
}
}
}