diff options
author | vnugent <public@vaughnnugent.com> | 2023-11-02 01:49:02 -0400 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2023-11-02 01:49:02 -0400 |
commit | 9e3dd9be0f0ec7aaef1a719f09f96425e66369df (patch) | |
tree | 59b8bd4ace8750327db80823fa1e5eccdf44bc74 /lib/Net.Http | |
parent | eafefadc4b858e5b5be481662a2b0c8e47a43bf4 (diff) |
may have gottem carried away
Diffstat (limited to 'lib/Net.Http')
-rw-r--r-- | lib/Net.Http/src/Core/Buffering/SplitHttpBufferElement.cs | 4 | ||||
-rw-r--r-- | lib/Net.Http/src/Core/TransportReader.cs | 76 |
2 files changed, 65 insertions, 15 deletions
diff --git a/lib/Net.Http/src/Core/Buffering/SplitHttpBufferElement.cs b/lib/Net.Http/src/Core/Buffering/SplitHttpBufferElement.cs index e65ffd8..103d723 100644 --- a/lib/Net.Http/src/Core/Buffering/SplitHttpBufferElement.cs +++ b/lib/Net.Http/src/Core/Buffering/SplitHttpBufferElement.cs @@ -26,6 +26,8 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using VNLib.Utils.Memory; + namespace VNLib.Net.Http.Core.Buffering { internal abstract class SplitHttpBufferElement : HttpBufferElement, ISplitHttpBuffer @@ -65,6 +67,6 @@ namespace VNLib.Net.Http.Core.Buffering /// </summary> /// <param name="binSize">The desired size of the binary buffer</param> /// <returns>The total size of the binary buffer required to store the binary and character buffer</returns> - public static int GetfullSize(int binSize) => binSize + (binSize * sizeof(char)); + public static int GetfullSize(int binSize) => binSize + MemoryUtil.ByteCount<char>(binSize); } } diff --git a/lib/Net.Http/src/Core/TransportReader.cs b/lib/Net.Http/src/Core/TransportReader.cs index 58c23df..8d605d1 100644 --- a/lib/Net.Http/src/Core/TransportReader.cs +++ b/lib/Net.Http/src/Core/TransportReader.cs @@ -25,6 +25,9 @@ using System; using System.IO; using System.Text; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using VNLib.Utils; using VNLib.Utils.IO; @@ -36,8 +39,17 @@ namespace VNLib.Net.Http.Core /// <summary> /// Structure implementation of <see cref="IVnTextReader"/> /// </summary> - internal struct TransportReader : IVnTextReader + internal readonly struct TransportReader : IVnTextReader { + /* + * To make this structure read-only we can store the + * mutable values in a private segment of the internal + * buffer. 8 bytes are reserved at the beining and an + * additional word is added for padding incase small/wild + * under/over run occurs. + */ + const int PrivateBufferOffset = 4 * sizeof(int); + ///<inheritdoc/> public readonly Encoding Encoding { get; } @@ -47,10 +59,25 @@ namespace VNLib.Net.Http.Core ///<inheritdoc/> public readonly Stream BaseStream { get; } + /* + * Store the window start/end in the begging of the + * data buffer. Then use a constant offset to get the + * start of the buffer + */ + private readonly int BufWindowStart + { + get => MemoryMarshal.Read<int>(Buffer.GetBinSpan()); + set => MemoryMarshal.Write(Buffer.GetBinSpan(), ref value); + } + + private readonly int BufWindowEnd + { + get => MemoryMarshal.Read<int>(Buffer.GetBinSpan()[sizeof(int)..]); + set => MemoryMarshal.Write(Buffer.GetBinSpan()[sizeof(int)..], ref value); + } + private readonly IHttpHeaderParseBuffer Buffer; - - private int BufWindowStart; - private int BufWindowEnd; + private readonly int MAxBufferSize; /// <summary> /// Initializes a new <see cref="TransportReader"/> for reading text lines from the transport stream @@ -61,29 +88,50 @@ namespace VNLib.Net.Http.Core /// <param name="lineTermination">The line delimiter to search for</param> public TransportReader(Stream transport, IHttpHeaderParseBuffer buffer, Encoding encoding, ReadOnlyMemory<byte> lineTermination) { - BufWindowEnd = 0; - BufWindowStart = 0; Encoding = encoding; BaseStream = transport; LineTermination = lineTermination; Buffer = buffer; + MAxBufferSize = buffer.BinSize - PrivateBufferOffset; + + //Initialize the buffer window + SafeZeroPrivateSegments(Buffer); + + Debug.Assert(BufWindowEnd == 0 && BufWindowStart == 0); } + + /// <summary> + /// Clears the initial window start/end values with the + /// extra padding + /// </summary> + /// <param name="buffer">The buffer segment to initialize</param> + private static void SafeZeroPrivateSegments(IHttpHeaderParseBuffer buffer) + { + ref byte start = ref MemoryMarshal.GetReference(buffer.GetBinSpan()); + Unsafe.InitBlock(ref start, 0, PrivateBufferOffset); + } + + /// <summary> + /// Gets the data segment of the buffer after the private segment + /// </summary> + /// <returns></returns> + private readonly Span<byte> GetDataSegment() => Buffer.GetBinSpan()[PrivateBufferOffset..]; ///<inheritdoc/> public readonly int Available => BufWindowEnd - BufWindowStart; ///<inheritdoc/> - public readonly Span<byte> BufferedDataWindow => Buffer.GetBinSpan()[BufWindowStart..BufWindowEnd]; + public readonly Span<byte> BufferedDataWindow => GetDataSegment()[BufWindowStart..BufWindowEnd]; ///<inheritdoc/> - public void Advance(int count) => BufWindowStart += count; + public readonly void Advance(int count) => BufWindowStart += count; ///<inheritdoc/> - public void FillBuffer() + public readonly void FillBuffer() { //Get a buffer from the end of the current window to the end of the buffer - Span<byte> bufferWindow = Buffer.GetBinSpan()[BufWindowEnd..]; + Span<byte> bufferWindow = GetDataSegment()[BufWindowEnd..]; //Read from stream int read = BaseStream.Read(bufferWindow); @@ -93,15 +141,15 @@ namespace VNLib.Net.Http.Core } ///<inheritdoc/> - public ERRNO CompactBufferWindow() + public readonly ERRNO CompactBufferWindow() { //No data to compact if window is not shifted away from start if (BufWindowStart > 0) { //Get span over engire buffer - Span<byte> buffer = Buffer.GetBinSpan(); + Span<byte> buffer = GetDataSegment(); - //Get data within window + //Get used data segment within window Span<byte> usedData = buffer[BufWindowStart..BufWindowEnd]; //Copy remaining to the begining of the buffer @@ -115,7 +163,7 @@ namespace VNLib.Net.Http.Core } //Return the number of bytes of available space from the end of the current window - return Buffer.BinSize - BufWindowEnd; + return MAxBufferSize - BufWindowEnd; } } } |