Skip to main content

RUNTIME_SOURCE

Constant RUNTIME_SOURCE 

Source
pub const RUNTIME_SOURCE: &str = "// SPDX-License-Identifier: Apache-2.0\n// Copyright 2026 The Hyperlight Authors.\n\n// Support types for C# bindings generated by hyperlight-component-csharp.\n// The encoding is specified in docs/component-wire-format.md.\n\n#nullable enable\n// Members named after WIT types and object overrides need no docs.\n#pragma warning disable CS1591\n\nusing System;\nusing System.Buffers.Binary;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Hyperlight.Component\n{\n    /// <summary>Calls guest functions by wire name.</summary>\n    public interface IGuestCaller\n    {\n        /// <summary>\n        /// Calls <paramref name=\"function\"/> with one encoded buffer per\n        /// parameter and returns the encoded result.\n        /// </summary>\n        byte[] Call(string function, byte[][] args);\n    }\n\n    /// <summary>Registers host functions by wire name.</summary>\n    public interface IHostFunctionRegistry\n    {\n        /// <summary>\n        /// Registers <paramref name=\"implementation\"/>, which receives one\n        /// encoded buffer per parameter and returns the encoded result.\n        /// </summary>\n        void Register(string function, int parameterCount, Func<byte[][], byte[]> implementation);\n    }\n\n    /// <summary>Thrown when encoded data does not match the expected type.</summary>\n    public sealed class WireFormatException : Exception\n    {\n        public WireFormatException(string message) : base(message) { }\n    }\n\n    /// <summary>The payload of a <c>result</c> case without a type.</summary>\n    public readonly struct Unit : IEquatable<Unit>\n    {\n        public bool Equals(Unit other) => true;\n        public override bool Equals(object? obj) => obj is Unit;\n        public override int GetHashCode() => 0;\n        public override string ToString() => \"()\";\n\n        public static bool operator ==(Unit left, Unit right) => true;\n\n        public static bool operator !=(Unit left, Unit right) => false;\n    }\n\n    /// <summary>\n    /// A WIT <c>option</c> whose payload is itself an <c>option</c>.\n    /// Other options map to nullable types.\n    /// </summary>\n    public readonly struct Option<T> : IEquatable<Option<T>>\n    {\n        private readonly T _value;\n\n        private Option(T value)\n        {\n            HasValue = true;\n            _value = value;\n        }\n\n        public static Option<T> None => default;\n\n        public static Option<T> Some(T value) => new(value);\n\n        public bool HasValue { get; }\n\n        public T Value => HasValue ? _value : throw new InvalidOperationException(\"option has no value\");\n\n        public bool Equals(Option<T> other) =>\n            HasValue == other.HasValue && (!HasValue || EqualityComparer<T>.Default.Equals(_value, other._value));\n\n        public override bool Equals(object? obj) => obj is Option<T> other && Equals(other);\n\n        public override int GetHashCode() => HasValue ? HashCode.Combine(true, _value) : 0;\n\n        public override string ToString() => HasValue ? $\"Some({_value})\" : \"None\";\n\n        public static bool operator ==(Option<T> left, Option<T> right) => left.Equals(right);\n\n        public static bool operator !=(Option<T> left, Option<T> right) => !left.Equals(right);\n    }\n\n    /// <summary>A WIT <c>result</c>.</summary>\n    public readonly struct Result<TOk, TErr> : IEquatable<Result<TOk, TErr>>\n    {\n        private readonly TOk _ok;\n        private readonly TErr _err;\n\n        private Result(bool isOk, TOk ok, TErr err)\n        {\n            IsOk = isOk;\n            _ok = ok;\n            _err = err;\n        }\n\n        public static Result<TOk, TErr> FromOk(TOk value) => new(true, value, default!);\n\n        public static Result<TOk, TErr> FromErr(TErr value) => new(false, default!, value);\n\n        public bool IsOk { get; }\n\n        public TOk Ok => IsOk ? _ok : throw new InvalidOperationException(\"result is an error\");\n\n        public TErr Err => IsOk ? throw new InvalidOperationException(\"result is not an error\") : _err;\n\n        public bool Equals(Result<TOk, TErr> other) =>\n            IsOk == other.IsOk && (IsOk\n                ? EqualityComparer<TOk>.Default.Equals(_ok, other._ok)\n                : EqualityComparer<TErr>.Default.Equals(_err, other._err));\n\n        public override bool Equals(object? obj) => obj is Result<TOk, TErr> other && Equals(other);\n\n        public override int GetHashCode() =>\n            IsOk ? HashCode.Combine(true, _ok) : HashCode.Combine(false, _err);\n\n        public override string ToString() => IsOk ? $\"Ok({_ok})\" : $\"Err({_err})\";\n\n        public static bool operator ==(Result<TOk, TErr> left, Result<TOk, TErr> right) => left.Equals(right);\n\n        public static bool operator !=(Result<TOk, TErr> left, Result<TOk, TErr> right) => !left.Equals(right);\n    }\n\n    /// <summary>Encodes values in the Hyperlight component wire format.</summary>\n    public sealed class WireWriter\n    {\n        // Throws on lone surrogates, which a WIT string cannot hold.\n        private static readonly UTF8Encoding StrictUtf8 = new(false, true);\n\n        private byte[] _buffer;\n        private int _length;\n\n        public WireWriter(int capacity = 64)\n        {\n            _buffer = new byte[Math.Max(capacity, 1)];\n        }\n\n        /// <summary>The generated world\'s resource tables, for writing handles.</summary>\n        public object? Resources { get; init; }\n\n        /// <summary>The call that handles written here are given or lent in.</summary>\n        public CallScope? Scope { get; init; }\n\n        public byte[] ToArray() => _buffer.AsSpan(0, _length).ToArray();\n\n        public void Bool(bool value) => U8(value ? (byte)1 : (byte)0);\n\n        public void U8(byte value) => Grow(1)[0] = value;\n\n        public void S8(sbyte value) => Grow(1)[0] = unchecked((byte)value);\n\n        public void U16(ushort value) => BinaryPrimitives.WriteUInt16LittleEndian(Grow(2), value);\n\n        public void S16(short value) => BinaryPrimitives.WriteInt16LittleEndian(Grow(2), value);\n\n        public void U32(uint value) => BinaryPrimitives.WriteUInt32LittleEndian(Grow(4), value);\n\n        public void S32(int value) => BinaryPrimitives.WriteInt32LittleEndian(Grow(4), value);\n\n        public void U64(ulong value) => BinaryPrimitives.WriteUInt64LittleEndian(Grow(8), value);\n\n        public void S64(long value) => BinaryPrimitives.WriteInt64LittleEndian(Grow(8), value);\n\n        public void F32(float value) => BinaryPrimitives.WriteSingleLittleEndian(Grow(4), value);\n\n        public void F64(double value) => BinaryPrimitives.WriteDoubleLittleEndian(Grow(8), value);\n\n        public void Char(Rune value) => U32((uint)value.Value);\n\n        public void String(string value)\n        {\n            ArgumentNullException.ThrowIfNull(value);\n            var length = StrictUtf8.GetByteCount(value);\n            Length(length);\n            StrictUtf8.GetBytes(value, Grow(length));\n        }\n\n        /// <summary>Writes the element count of a <c>list</c>.</summary>\n        public void Length(int count) => U32(checked((uint)count));\n\n        /// <summary>Writes a <c>list&lt;u8&gt;</c>.</summary>\n        public void Bytes(byte[] value)\n        {\n            ArgumentNullException.ThrowIfNull(value);\n            Length(value.Length);\n            value.CopyTo(Grow(value.Length));\n        }\n\n        /// <summary>Writes a <c>list&lt;u8, N&gt;</c>.</summary>\n        public void FixedBytes(byte[] value, int count)\n        {\n            CheckFixedLength(value, count);\n            value.CopyTo(Grow(count));\n        }\n\n        /// <summary>Writes the low <paramref name=\"byteCount\"/> bytes of a <c>flags</c> bitmask.</summary>\n        public void Flags(uint bits, int byteCount)\n        {\n            var bytes = Grow(byteCount);\n            for (var i = 0; i < byteCount; i++)\n            {\n                bytes[i] = (byte)(bits >> (8 * i));\n            }\n        }\n\n        /// <summary>Throws unless a fixed-length list has <paramref name=\"count\"/> elements.</summary>\n        public static void CheckFixedLength<T>(IReadOnlyCollection<T> value, int count)\n        {\n            ArgumentNullException.ThrowIfNull(value);\n            if (value.Count != count)\n            {\n                throw new ArgumentException($\"fixed-length list needs {count} elements, got {value.Count}\");\n            }\n        }\n\n        private Span<byte> Grow(int count)\n        {\n            if (_buffer.Length - _length < count)\n            {\n                Array.Resize(ref _buffer, Math.Max(checked(_length + count), _buffer.Length * 2));\n            }\n            var span = _buffer.AsSpan(_length, count);\n            _length += count;\n            return span;\n        }\n    }\n\n    /// <summary>Decodes values in the Hyperlight component wire format.</summary>\n    public ref struct WireReader\n    {\n        private static readonly UTF8Encoding StrictUtf8 = new(false, true);\n\n        private readonly ReadOnlySpan<byte> _data;\n        private int _position;\n\n        public WireReader(ReadOnlySpan<byte> data)\n        {\n            _data = data;\n            _position = 0;\n        }\n\n        /// <summary>The generated world\'s resource tables, for reading handles.</summary>\n        public object? Resources { get; init; }\n\n        public bool Bool() => U8() != 0;\n\n        public byte U8() => Take(1)[0];\n\n        public sbyte S8() => unchecked((sbyte)Take(1)[0]);\n\n        public ushort U16() => BinaryPrimitives.ReadUInt16LittleEndian(Take(2));\n\n        public short S16() => BinaryPrimitives.ReadInt16LittleEndian(Take(2));\n\n        public uint U32() => BinaryPrimitives.ReadUInt32LittleEndian(Take(4));\n\n        public int S32() => BinaryPrimitives.ReadInt32LittleEndian(Take(4));\n\n        public ulong U64() => BinaryPrimitives.ReadUInt64LittleEndian(Take(8));\n\n        public long S64() => BinaryPrimitives.ReadInt64LittleEndian(Take(8));\n\n        public float F32() => BinaryPrimitives.ReadSingleLittleEndian(Take(4));\n\n        public double F64() => BinaryPrimitives.ReadDoubleLittleEndian(Take(8));\n\n        public Rune Char()\n        {\n            var value = U32();\n            if (!Rune.IsValid(value))\n            {\n                throw new WireFormatException($\"invalid char {value:x}\");\n            }\n            return new Rune(value);\n        }\n\n        public string String()\n        {\n            var bytes = Take(Length());\n            try\n            {\n                return StrictUtf8.GetString(bytes);\n            }\n            catch (DecoderFallbackException e)\n            {\n                throw new WireFormatException($\"invalid UTF-8: {e.Message}\");\n            }\n        }\n\n        /// <summary>Reads the element count of a <c>list</c>.</summary>\n        public int Length()\n        {\n            var count = U32();\n            // Every element takes at least one byte.\n            if (count > (uint)(_data.Length - _position))\n            {\n                throw new WireFormatException($\"list length {count} exceeds remaining input\");\n            }\n            return (int)count;\n        }\n\n        /// <summary>Reads a <c>list&lt;u8&gt;</c>.</summary>\n        public byte[] Bytes() => Take(Length()).ToArray();\n\n        /// <summary>Reads a <c>list&lt;u8, N&gt;</c>.</summary>\n        public byte[] FixedBytes(int count) => Take(count).ToArray();\n\n        /// <summary>Reads a four byte tag that must be below <paramref name=\"cases\"/>.</summary>\n        public uint Tag32(uint cases)\n        {\n            var tag = U32();\n            if (tag >= cases)\n            {\n                throw new WireFormatException($\"invalid tag {tag}\");\n            }\n            return tag;\n        }\n\n        /// <summary>\n        /// Reads a <c>flags</c> bitmask of <paramref name=\"byteCount\"/> bytes\n        /// and keeps the bits in <paramref name=\"mask\"/>.\n        /// </summary>\n        public uint Flags(int byteCount, uint mask)\n        {\n            var bytes = Take(byteCount);\n            uint bits = 0;\n            for (var i = 0; i < byteCount; i++)\n            {\n                bits |= (uint)bytes[i] << (8 * i);\n            }\n            return bits & mask;\n        }\n\n        private ReadOnlySpan<byte> Take(int count)\n        {\n            if ((uint)count > (uint)(_data.Length - _position))\n            {\n                throw new WireFormatException(\"unexpected end of input\");\n            }\n            var span = _data.Slice(_position, count);\n            _position += count;\n            return span;\n        }\n    }\n\n    /// <summary>\n    /// Host objects of one resource type that the guest refers to by\n    /// handle. A handle is an index into the table.\n    /// </summary>\n    public sealed class ResourceTable<T> where T : class\n    {\n        private readonly List<Entry> _entries = new();\n\n        private sealed class Entry\n        {\n            public T? Value;\n            public bool Lent;\n        }\n\n        /// <summary>\n        /// Gives <paramref name=\"value\"/> to the guest. With\n        /// <paramref name=\"scope\"/>, the gift is undone unless the call\n        /// starts.\n        /// </summary>\n        public uint Give(T value, CallScope? scope = null)\n        {\n            var handle = Add(value, lent: false);\n            scope?.AddGift(() => Clear(handle));\n            return handle;\n        }\n\n        /// <summary>Lends <paramref name=\"value\"/> to the guest until <paramref name=\"scope\"/> ends.</summary>\n        public uint Lend(T value, CallScope scope)\n        {\n            ArgumentNullException.ThrowIfNull(scope);\n            var handle = Add(value, lent: true);\n            scope.AddLoan(() => Clear(handle));\n            return handle;\n        }\n\n        private void Clear(uint handle)\n        {\n            lock (_entries)\n            {\n                _entries[(int)handle].Value = null;\n            }\n        }\n\n        /// <summary>Takes back a value the guest owns.</summary>\n        public T Take(uint handle)\n        {\n            lock (_entries)\n            {\n                var entry = Get(handle);\n                if (entry.Lent || entry.Value is null)\n                {\n                    throw new WireFormatException($\"resource handle {handle} is not owned\");\n                }\n                var value = entry.Value;\n                entry.Value = null;\n                return value;\n            }\n        }\n\n        /// <summary>Returns the value for a handle the guest lends back to the host.</summary>\n        public T Borrow(uint handle)\n        {\n            lock (_entries)\n            {\n                return Get(handle).Value ?? throw new WireFormatException($\"resource handle {handle} is not valid\");\n            }\n        }\n\n        private uint Add(T value, bool lent)\n        {\n            ArgumentNullException.ThrowIfNull(value);\n            lock (_entries)\n            {\n                _entries.Add(new Entry { Value = value, Lent = lent });\n                return checked((uint)(_entries.Count - 1));\n            }\n        }\n\n        private Entry Get(uint handle) =>\n            handle < (uint)_entries.Count\n                ? _entries[(int)handle]\n                : throw new WireFormatException($\"invalid resource handle {handle}\");\n    }\n\n    /// <summary>\n    /// Resources lent to the guest for one call, and resources given to it\n    /// before the call starts.\n    /// </summary>\n    public sealed class CallScope\n    {\n        private List<Action>? _loans;\n        private List<Action>? _gifts;\n\n        internal void AddLoan(Action revoke) => (_loans ??= new()).Add(revoke);\n\n        internal void AddGift(Action undo) => (_gifts ??= new()).Add(undo);\n\n        /// <summary>Marks the call as started, which completes the gifts.</summary>\n        public void Commit() => _gifts?.Clear();\n\n        /// <summary>Revokes every loan, and undoes gifts made before <see cref=\"Commit\"/>.</summary>\n        public void End()\n        {\n            Run(_gifts);\n            Run(_loans);\n        }\n\n        private static void Run(List<Action>? actions)\n        {\n            if (actions is null)\n            {\n                return;\n            }\n            foreach (var action in actions)\n            {\n                action();\n            }\n            actions.Clear();\n        }\n    }\n}\n";
Expand description

C# source for the Hyperlight.Component namespace that generated bindings depend on.