Code/Wasm/MemorySection.cs
using System;
using System.Collections.Generic;
using System.IO;
using WasmBox.Wasm.Binary;
namespace WasmBox.Wasm {
/// <summary>
/// A type of section that defines zero or more memories.
/// </summary>
public sealed class MemorySection : Section {
/// <summary>
/// Creates an empty memory section.
/// </summary>
public MemorySection() {
this.Memories = new List<MemoryType>();
this.ExtraPayload = new byte[0];
}
/// <summary>
/// Creates a memory section from the given sequence of memory specifications.
/// </summary>
public MemorySection(IEnumerable<MemoryType> memories)
: this(memories, new byte[0]) {
}
/// <summary>
/// Creates a memory section from the given sequence of memory specifications
/// and a trailing byte array.
/// </summary>
public MemorySection(IEnumerable<MemoryType> memories, byte[] extraPayload) {
this.Memories = new List<MemoryType>(memories);
this.ExtraPayload = extraPayload;
}
/// <inheritdoc/>
public override SectionName Name => new SectionName(SectionCode.Memory);
/// <summary>
/// Gets a list that contains the limits of all memories defined by this section.
/// </summary>
/// <returns>The section's list of memory limits.</returns>
public List<MemoryType> Memories { get; private set; }
/// <summary>
/// Gets this memory section's additional payload.
/// </summary>
/// <returns>The additional payload, as an array of bytes.</returns>
public byte[] ExtraPayload { get; set; }
/// <inheritdoc/>
public override void WritePayloadTo(BinaryWasmWriter writer) {
writer.WriteVarUInt32((uint)Memories.Count);
foreach (var limits in Memories) {
limits.WriteTo(writer);
}
writer.Writer.Write(ExtraPayload);
}
/// <inheritdoc/>
public override void Dump(TextWriter writer) {
writer.Write(Name.ToString());
writer.Write("; number of entries: ");
writer.Write(Memories.Count);
writer.WriteLine();
for (int i = 0; i < Memories.Count; i++) {
writer.Write("#");
writer.Write(i);
writer.Write(" -> ");
Memories[i].Dump(writer);
writer.WriteLine();
}
if (ExtraPayload.Length > 0) {
writer.Write("Extra payload size: ");
writer.Write(ExtraPayload.Length);
writer.WriteLine();
DumpHelpers.DumpBytes(ExtraPayload, writer);
writer.WriteLine();
}
}
/// <summary>
/// Reads the memory section with the given header.
/// </summary>
/// <param name="header">The section header.</param>
/// <param name="reader">The WebAssembly file reader.</param>
/// <returns>The parsed section.</returns>
public static MemorySection ReadSectionPayload(SectionHeader header, BinaryWasmReader reader) {
long startPos = reader.Position;
// Read the resizable limits.
uint count = reader.ReadVarUInt32();
var limits = new List<MemoryType>();
for (uint i = 0; i < count; i++) {
limits.Add(MemoryType.ReadFrom(reader));
}
// Skip any remaining bytes.
var extraPayload = reader.ReadRemainingPayload(startPos, header);
return new MemorySection(limits, extraPayload);
}
}
/// <summary>
/// Describes a linear memory.
/// </summary>
public sealed class MemoryType {
/// <summary>
/// Creates a new linear memory description from the given limits.
/// </summary>
/// <param name="limits">The linear memory's limits.</param>
public MemoryType(ResizableLimits limits) {
this.Limits = limits;
}
/// <summary>
/// Gets this memory's limits.
/// </summary>
/// <returns>This memory's limits.</returns>
public ResizableLimits Limits { get; set; }
/// <summary>
/// Gets the size of a single page, in bytes.
/// </summary>
public const uint PageSize = 64 * 1024;
/// <summary>
/// Writes this memory description to the given binary WebAssembly file.
/// </summary>
/// <param name="writer">The writer for a binary WebAssembly file.</param>
public void WriteTo(BinaryWasmWriter writer) {
Limits.WriteTo(writer);
}
/// <summary>
/// Writes a textual representation of this memory description to the given writer.
/// </summary>
/// <param name="writer">The writer to which text is written.</param>
public void Dump(TextWriter writer) {
Limits.Dump(writer);
}
/// <summary>
/// Reads a single memory description from the given reader.
/// </summary>
/// <returns>The memory description.</returns>
public static MemoryType ReadFrom(BinaryWasmReader reader) {
return new MemoryType(reader.ReadResizableLimits());
}
}
}