/// <summary> /// Searches for 2 sequential bytes in the <see cref="ReadOnlyBuffer"/> and returns a sliced <see cref="ReadOnlyBuffer"/> that /// contains all data up to and excluding the first byte, and a <see cref="SequencePosition"/> that points to the second byte. /// </summary> /// <param name="b1">The first byte to search for</param> /// <param name="b2">The second byte to search for</param> /// <param name="slice">A <see cref="ReadOnlyBuffer"/> slice that contains all data up to and excluding the first byte.</param> /// <param name="cursor">A <see cref="SequencePosition"/> that points to the second byte</param> /// <returns>True if the byte sequence was found, false if not found</returns> public static unsafe bool TrySliceTo(this ReadOnlyBuffer <byte> buffer, byte b1, byte b2, out ReadOnlyBuffer <byte> slice, out SequencePosition cursor) { // use address of ushort rather than stackalloc as the inliner won't inline functions with stackalloc ushort twoBytes; byte * byteArray = (byte *)&twoBytes; byteArray[0] = b1; byteArray[1] = b2; return(buffer.TrySliceTo(new Span <byte>(byteArray, 2), out slice, out cursor)); }
public override TPackageInfo Filter(ref ReadOnlyBuffer <byte> buffer) { ReadOnlyBuffer <byte> slice; Position cursor; if (!buffer.TrySliceTo(new Span <byte>(_terminator), out slice, out cursor)) { return(null); } buffer = buffer.Slice(cursor).Slice(_terminator.Length); return(ResolvePackage(slice)); }
public bool TryDecode(ref ReadOnlyBuffer input, out Line frame) { if (input.TrySliceTo((byte)'\r', (byte)'\n', out ReadOnlyBuffer slice, out Position cursor)) { frame = new Line { Data = slice.GetUtf8Span() }; input = input.Slice(cursor).Slice(1); return(true); } frame = null; return(false); }
private unsafe void TestIndexOfWorksForAllLocations(ref ReadOnlyBuffer <byte> readBuffer, byte emptyValue) { byte huntValue = (byte)~emptyValue; var handles = new List <MemoryHandle>(); // we're going to fully index the final locations of the buffer, so that we // can mutate etc in constant time var addresses = BuildPointerIndex(ref readBuffer, handles); var found = readBuffer.TrySliceTo(huntValue, out ReadOnlyBuffer <byte> slice, out Position cursor); Assert.False(found); // correctness test all values for (int i = 0; i < readBuffer.Length; i++) { *addresses[i] = huntValue; found = readBuffer.TrySliceTo(huntValue, out slice, out cursor); *addresses[i] = emptyValue; Assert.True(found); var remaining = readBuffer.Slice(cursor); var handle = remaining.First.Retain(pin: true); Assert.True(handle.Pointer != null); if (i % BlockSize == 0) { Assert.True((byte *)handle.Pointer == addresses[i]); } handle.Dispose(); } // free up memory handles foreach (var handle in handles) { handle.Dispose(); } handles.Clear(); }
public ParseResult ParseRequest(ReadOnlyBuffer buffer, out Position consumed, out Position examined) { consumed = buffer.Start; examined = buffer.Start; if (_state == ParsingState.StartLine) { if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out ReadOnlyBuffer startLine, out Position delim)) { return(ParseResult.Incomplete); } // Move the buffer to the rest buffer = buffer.Slice(delim).Slice(2); if (!startLine.TrySliceTo((byte)' ', out ReadOnlyBuffer method, out delim)) { return(ParseResult.BadRequest); } _method = method.ToArray(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); if (!startLine.TrySliceTo((byte)' ', out ReadOnlyBuffer path, out delim)) { return(ParseResult.BadRequest); } _path = path.ToArray(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); var httpVersion = startLine; if (httpVersion.IsEmpty) { return(ParseResult.BadRequest); } _httpVersion = httpVersion.ToArray(); _state = ParsingState.Headers; consumed = buffer.Start; examined = buffer.Start; } // Parse headers // key: value\r\n while (!buffer.IsEmpty) { var headerValue = default(ReadOnlyBuffer); if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out ReadOnlyBuffer headerPair, out Position delim)) { return(ParseResult.Incomplete); } buffer = buffer.Slice(delim).Slice(2); consumed = buffer.Start; examined = buffer.Start; // End of headers if (headerPair.IsEmpty) { return(ParseResult.Complete); } // : if (!headerPair.TrySliceTo((byte)':', out ReadOnlyBuffer headerName, out delim)) { return(ParseResult.BadRequest); } headerName = headerName.TrimStart(); headerPair = headerPair.Slice(delim).Slice(1); headerValue = headerPair.TrimStart(); RequestHeaders.SetHeader(ref headerName, ref headerValue); } return(ParseResult.Incomplete); }