Ejemplo n.º 1
0
    // 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);
        }
    }