aboutsummaryrefslogtreecommitdiff
path: root/lib/Net.Http
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-11-02 01:49:02 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-11-02 01:49:02 -0400
commit9e3dd9be0f0ec7aaef1a719f09f96425e66369df (patch)
tree59b8bd4ace8750327db80823fa1e5eccdf44bc74 /lib/Net.Http
parenteafefadc4b858e5b5be481662a2b0c8e47a43bf4 (diff)
may have gottem carried away
Diffstat (limited to 'lib/Net.Http')
-rw-r--r--lib/Net.Http/src/Core/Buffering/SplitHttpBufferElement.cs4
-rw-r--r--lib/Net.Http/src/Core/TransportReader.cs76
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;
}
}
}