17 ReadOnlyMemory<byte> data,
22 ValidateProcessor(processor);
25 throw new InvalidDataException(
"The ELF input exceeds the configured allocation limit.");
28 NdsElfFile elf = NdsElfParser.Parse(data, effectiveOptions);
29 return NdsElfAssembler.Assemble(data, elf, processor, effectiveOptions);
38 public static async ValueTask<NdsElfImportResult>
ImportAsync(
42 CancellationToken cancellationToken =
default)
44 ArgumentException.ThrowIfNullOrWhiteSpace(path);
46 ValidateProcessor(processor);
47 var stream =
new FileStream(
53 FileOptions.Asynchronous | FileOptions.SequentialScan);
54 await
using (stream.ConfigureAwait(
false))
56 return await
ImportAsync(stream, processor, leaveOpen:
true, effectiveOptions, cancellationToken).ConfigureAwait(
false);
70 public static async ValueTask<NdsElfImportResult>
ImportAsync(
73 bool leaveOpen =
false,
75 CancellationToken cancellationToken =
default)
77 ArgumentNullException.ThrowIfNull(stream);
79 ValidateProcessor(processor);
84 throw new ArgumentException(
"The ELF source stream must be readable.", nameof(stream));
87 byte[] data = await ReadBoundedAsync(stream, effectiveOptions.
MaxInputBytes, cancellationToken).ConfigureAwait(
false);
88 return Import(data, processor, effectiveOptions);
94 await stream.DisposeAsync().ConfigureAwait(
false);
104 private static async ValueTask<byte[]> ReadBoundedAsync(
107 CancellationToken cancellationToken)
109 if (source.CanSeek && source.Length - source.Position > limit)
111 throw new InvalidDataException(
"The ELF input exceeds the configured allocation limit.");
114 byte[] buffer = ArrayPool<byte>.Shared.Rent(64 * 1024);
117 using var output =
new MemoryStream();
120 int count = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(
false);
123 return output.ToArray();
126 if (output.Length > limit - count)
128 throw new InvalidDataException(
"The ELF input exceeds the configured allocation limit.");
131 await output.WriteAsync(buffer.AsMemory(0, count), cancellationToken).ConfigureAwait(
false);
136 ArrayPool<byte>.Shared.Return(buffer, clearArray:
true);
143 private static NdsElfImportOptions Snapshot(NdsElfImportOptions? options)
145 options ??= NdsElfImportOptions.Default;
146 var snapshot =
new NdsElfImportOptions
148 MaxInputBytes = options.MaxInputBytes,
149 MaxProgramBytes = options.MaxProgramBytes,
150 MaxProgramHeaders = options.MaxProgramHeaders,
151 MaxOverlays = options.MaxOverlays,
152 ImportOverlays = options.ImportOverlays,
160 private static void ValidateProcessor(
NdsProcessor processor)
162 if (!Enum.IsDefined(processor))
164 throw new ArgumentOutOfRangeException(nameof(processor), processor,
"Unknown NDS processor identity.");
static async ValueTask< NdsElfImportResult > ImportAsync(Stream stream, NdsProcessor processor, bool leaveOpen=false, NdsElfImportOptions? options=null, CancellationToken cancellationToken=default)
Consumes ELF bytes from a stream's current position, including non-seekable sources,...
static NdsElfImportResult Import(ReadOnlyMemory< byte > data, NdsProcessor processor, NdsElfImportOptions? options=null)
Imports an ELF already available in memory without retaining or mutating the caller's buffer.
static async ValueTask< NdsElfImportResult > ImportAsync(string path, NdsProcessor processor, NdsElfImportOptions? options=null, CancellationToken cancellationToken=default)
Reads and imports a filesystem ELF after checking its length before allocation.