// Return (as a DateTimeOffset) the value corresponding to the query string parameter "startTime". // queryString is expected to be "a=b&c=d&...", without leading question mark. static DateTimeOffset ExtractStartDate(ReadOnlySpan <byte> queryString) { byte[] scratch = ArrayPool <byte> .Shared.Rent(64); // worst case scenario for decoding try { foreach (var segment in Utf8.Split(queryString, '&')) { // segment reads "a=b" int index = segment.IndexOf((byte)'='); // Span<T>.IndexOf extension method if (index < 9 /* "startTime".Length */) { // no '=' found, or key can't possibly be "startTime" continue; } var urlEncodedKeyNameAsUtf8 = segment.Slice(0, index); var decodeStatus = UrlEncoder.Default.Decode(urlEncodedKeyNameAsUtf8, scratch, out var bytesConsumed, out var bytesWritten, isQueryString: true); if (decodeStatus != OperationStatus.Done) { continue; // bad key name - skip } var urlDecodedKeyNameAsUtf8 = scratch.AsSpan(0, bytesWritten); if (!Utf8.AreEqual(urlDecodedKeyNameAsUtf8, utf8 "startTime", stringComparison: StringComparison.OrdinalIgnoreCase)) { continue; // incorrect key name - skip } // At this point we're done with the scratch buffer so can reuse it. decodeStatus = UrlEncoder.Default.Decode(segment.Slice(index + 1), scratch, out bytesConsumed, out bytesWritten, isQueryString: true); if (decodeStatus != OperationStatus.Done) { continue; // bad value - skip } var urlDecodedValueAsUtf8 = scratch.AsSpan(0, bytesWritten); if (Utf8Parser.TryParse(urlDecodedValueAsUtf8, out DateTimeOffset value, out bytesConsumed) && bytesConsumed == urlDecodedValueAsUtf8.Length) { return(value); // success! } } throw new Exception("Couldn't extract start date."); // or return sentinel value indicating failure } finally { ArrayPool <byte> .Shared.Return(scratch); } }