using System;
namespace Wasmtime
{
///
/// Represents a mutable WebAssembly global value.
///
public class MutableGlobal : IDisposable
{
///
/// The value of the global.
///
public T Value
{
get
{
if (Handle is null)
{
throw new InvalidOperationException("The global cannot be used before it is instantiated.");
}
unsafe
{
var v = stackalloc Interop.wasm_val_t[1];
Interop.wasm_global_get(Handle.DangerousGetHandle(), v);
return (T)Interop.ToObject(v);
}
}
set
{
if (Handle is null)
{
throw new InvalidOperationException("The global cannot be used before it is instantiated.");
}
var v = Interop.ToValue(value, Kind);
unsafe
{
Interop.wasm_global_set(Handle.DangerousGetHandle(), &v);
}
}
}
///
/// Gets the value kind of the global.
///
///
public ValueKind Kind { get; private set; }
///
public void Dispose()
{
if (!Handle.IsInvalid)
{
Handle.Dispose();
Handle.SetHandleAsInvalid();
}
}
internal MutableGlobal(Interop.StoreHandle store, T initialValue)
{
if (!Interop.TryGetValueKind(typeof(T), out var kind))
{
throw new WasmtimeException($"Mutable global variables cannot be of type '{typeof(T).ToString()}'.");
}
Kind = kind;
var value = Interop.ToValue((object)initialValue, Kind);
var valueType = Interop.wasm_valtype_new(value.kind);
var valueTypeHandle = valueType.DangerousGetHandle();
valueType.SetHandleAsInvalid();
using var globalType = Interop.wasm_globaltype_new(
valueTypeHandle,
Interop.wasm_mutability_t.WASM_VAR
);
unsafe
{
Handle = Interop.wasm_global_new(store, globalType, &value);
if (Handle.IsInvalid)
{
throw new WasmtimeException("Failed to create mutable Wasmtime global.");
}
}
}
internal Interop.GlobalHandle Handle { get; set; }
}
}