aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Net.Http/src/Core/Response/ResponsBodyDataState.cs6
-rw-r--r--lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs60
-rw-r--r--lib/Utils/src/Extensions/MemoryExtensions.cs25
3 files changed, 69 insertions, 22 deletions
diff --git a/lib/Net.Http/src/Core/Response/ResponsBodyDataState.cs b/lib/Net.Http/src/Core/Response/ResponsBodyDataState.cs
index 797d490..bd43def 100644
--- a/lib/Net.Http/src/Core/Response/ResponsBodyDataState.cs
+++ b/lib/Net.Http/src/Core/Response/ResponsBodyDataState.cs
@@ -3,10 +3,10 @@
*
* Library: VNLib
* Package: VNLib.Net.Http
-* File: ResponseWriter.cs
+* File: ResponsBodyDataState.cs
*
-* ResponseWriter.cs is part of VNLib.Net.Http which is part of the larger
-* VNLib collection of libraries and utilities.
+* ResponsBodyDataState.cs is part of VNLib.Net.Http which is part of
+* the larger VNLib collection of libraries and utilities.
*
* VNLib.Net.Http is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
diff --git a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
index 66155dd..0ca5b8f 100644
--- a/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
+++ b/lib/Plugins.Essentials/src/Extensions/EssentialHttpEventExtensions.cs
@@ -796,6 +796,66 @@ namespace VNLib.Plugins.Essentials.Extensions
//Parse the file using the specified parser
return parser(file.FileData, file.ContentTypeString());
}
+
+ /// <summary>
+ /// Reads the contents of an uploaded file at the desired intex into memory
+ /// and returns a managed byte array containing the file data
+ /// </summary>
+ /// <param name="ev"></param>
+ /// <param name="uploadIndex">The index of the uploaded file to buffer</param>
+ /// <returns>A value task that resolves the uploaded data</returns>
+ /// <exception cref="IOException"></exception>
+ public static ValueTask<byte[]> ReadFileDataAsync(this HttpEntity ev, int uploadIndex = 0)
+ {
+ ArgumentNullException.ThrowIfNull(ev);
+
+ /*
+ * File should exist at the desired index and have a length greater than 0
+ * otherwise return an empty buffer
+ */
+ if (ev.Files.Count <= uploadIndex || ev.Files[uploadIndex].Length == 0)
+ {
+ return ValueTask.FromResult(Array.Empty<byte>());
+ }
+
+ return ReadFileDataAsync(ev, uploadIndex);
+
+ static async ValueTask<byte[]> ReadFileDataAsync(HttpEntity entity, int fileIndex)
+ {
+ FileUpload upload = entity.Files[fileIndex];
+
+ /*
+ * Alloc an uninitialized buffer to read the file data into, it should ALL
+ * be overwritten during read operation
+ */
+ byte[] buffer = GC.AllocateUninitializedArray<byte>((int)upload.Length);
+
+ int read = 0;
+
+ do
+ {
+ Memory<byte> mem = buffer.AsMemory(read, buffer.Length - read);
+
+ int r = await upload.FileData.ReadAsync(mem, entity.EventCancellation);
+
+ //If no data was read force break and deal with read data
+ if (r == 0)
+ {
+ break;
+ }
+
+ read += r;
+ } while (read < buffer.Length);
+
+ //Buffer is exact length, so read should be equal to length
+ if (read != buffer.Length)
+ {
+ throw new IOException("Failed to read entire file data, this may be an internal error");
+ }
+
+ return buffer;
+ }
+ }
/// <summary>
/// Get a <see cref="DirectoryInfo"/> instance that points to the current sites filesystem root.
diff --git a/lib/Utils/src/Extensions/MemoryExtensions.cs b/lib/Utils/src/Extensions/MemoryExtensions.cs
index 083c7cf..c433527 100644
--- a/lib/Utils/src/Extensions/MemoryExtensions.cs
+++ b/lib/Utils/src/Extensions/MemoryExtensions.cs
@@ -146,8 +146,13 @@ namespace VNLib.Utils.Extensions
/// <exception cref="OutOfMemoryException"></exception>
/// <exception cref="ObjectDisposedException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static MemoryManager<T> DirectAlloc<T>(this IUnmangedHeap heap, nuint size, bool zero = false) where T : unmanaged
+ public static MemoryManager<T> DirectAlloc<T>(this IUnmangedHeap heap, int size, bool zero = false) where T : unmanaged
{
+ /*
+ * Size it limited to int32 because the memory manager uses int32 for length
+ * and the constructor will attempt to cast the size to int32 or cause an
+ * overflow exception
+ */
MemoryHandle<T> handle = heap.Alloc<T>(size, zero);
return new SysBufferMemoryManager<T>(handle, true);
}
@@ -177,24 +182,6 @@ namespace VNLib.Utils.Extensions
//Method only exists for consistancy since unsafe handles are always 32bit
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetIntLength<T>(this in UnsafeMemoryHandle<T> handle) where T : unmanaged => handle.IntLength;
-
- /// <summary>
- /// Allows direct allocation of a fixed size <see cref="MemoryManager{T}"/> from a <see cref="IUnmangedHeap"/> instance
- /// of the specified number of elements
- /// </summary>
- /// <typeparam name="T">The unmanaged data type</typeparam>
- /// <param name="heap"></param>
- /// <param name="size">The number of elements to allocate on the heap</param>
- /// <param name="zero">Optionally zeros conents of the block when allocated</param>
- /// <returns>The <see cref="MemoryManager{T}"/> wrapper around the block of memory</returns>
- /// <exception cref="OverflowException"></exception>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static MemoryManager<T> DirectAlloc<T>(this IUnmangedHeap heap, nint size, bool zero = false) where T : unmanaged
- {
- ArgumentOutOfRangeException.ThrowIfNegative(size);
- return DirectAlloc<T>(heap, (nuint)size, zero);
- }
/// <summary>
/// Gets an offset pointer from the base postion to the number of bytes specified. Performs bounds checks