<commit_before>﻿using System.Text.Utf8;

namespace System.Net.Http.Buffered
{
    // TODO: I would like to use Utf8String instead of this type.
    // But the issue is that this type "borrows" native bytespan, and I don't want to make Utf8String unsafe
    public struct Utf8Span
    {
        static ByteSpan CreateEmptyByteSpan()
        {
            unsafe { return new ByteSpan(null, 0); }
        }
        static Utf8Span s_empty = new Utf8Span(CreateEmptyByteSpan());
        ByteSpan _bytes;

        public Utf8Span(ByteSpan bytes)
        {
            _bytes = bytes;
        }

        public static Utf8Span Empty { get { return s_empty; } }

        public int Length
        {
            get { return _bytes.Length; }
        }

        public override bool Equals(object obj)
        {
            throw new InvalidOperationException("this should not be called");
        }

        public bool Equals(Utf8String other)
        {
            if (Length != other.Length) return false;
            for(int i=0; i<Length; i++) {
                if (_bytes[i] != other.Bytes[i]) return false;
            }
            return true;
        }

        public override int GetHashCode()
        {
            throw new InvalidOperationException("you don't want it in a hashtable, do you?");
        }
    }

    public enum HttpMethod : byte
    {
        Unknown = 0,
        Get,
        Post,
        Put,
        Delete,
    }

    public enum HttpVersion : byte
    {
        Unknown = 0,
        V1_0,
        V1_1,
        V2_0,
    }

    public struct HttpRequestLine
    {
        public HttpMethod Method;
        public HttpVersion Version;
        public Utf8Span RequestUri;

        public override string ToString()
        {
            return RequestUri.ToString();
        }
    }

    public struct HttpRequestReader
    {
        static readonly Utf8String s_Http1_0 = new Utf8String("HTTP/1.0");
        static readonly Utf8String s_Http1_1 = new Utf8String("HTTP/1.1");
        static readonly Utf8String s_Http2_0 = new Utf8String("HTTP/2.0");

        internal const byte s_SP = 32; // space
        internal const byte s_CR = 13; // carriage return
        internal const byte s_LF = 10; // line feed
        internal const byte s_HT = 9;   // horizontal TAB

        public ByteSpan Buffer;

        public HttpMethod ReadMethod()
        {
            HttpMethod method;
            int parsedBytes;
            if (!HttpRequestParser.TryParseMethod(Buffer, out method, out parsedBytes))
            {
                return HttpMethod.Unknown;
            }
            Buffer = Buffer.Slice(parsedBytes);
            return method;
        }

        public Utf8Span ReadRequestUri()
        {
            Utf8Span requestUri;
            int parsedBytes;
            if (!HttpRequestParser.TryParseRequestUri(Buffer, out requestUri, out parsedBytes))
            {
                return Utf8Span.Empty;
            }
            Buffer = Buffer.Slice(parsedBytes);
            return requestUri;
        }

        Utf8Span ReadHttpVersionAsUtf8String()
        {
            Utf8Span httpVersion;
            int parsedBytes;
            if (!HttpRequestParser.TryParseHttpVersion(Buffer, out httpVersion, out parsedBytes))
            {
                return Utf8Span.Empty;
            }
            Buffer = Buffer.Slice(parsedBytes);
            return httpVersion;
        }

        public HttpVersion ReadHttpVersion()
        {
            ByteSpan oldBuffer = Buffer;
            Utf8Span version = ReadHttpVersionAsUtf8String();

            if (version.Equals(s_Http1_1))
            {
                return HttpVersion.V1_1;
            }
            else if (version.Equals(s_Http2_0))
            {
                return HttpVersion.V2_0;
            }
            else if (version.Equals(s_Http2_0))
            {
                return HttpVersion.V1_0;
            }
            else
            {
                Buffer = oldBuffer;
                return HttpVersion.Unknown;
            }
        }

        public Utf8Span ReadHeader()
        {<commit_msg>Fix version parsing bug in web server demo<commit_after>﻿using System.Text.Utf8;

namespace System.Net.Http.Buffered
{
    // TODO: I would like to use Utf8String instead of this type.
    // But the issue is that this type "borrows" native bytespan, and I don't want to make Utf8String unsafe
    public struct Utf8Span
    {
        static ByteSpan CreateEmptyByteSpan()
        {
            unsafe { return new ByteSpan(null, 0); }
        }
        static Utf8Span s_empty = new Utf8Span(CreateEmptyByteSpan());
        ByteSpan _bytes;

        public Utf8Span(ByteSpan bytes)
        {
            _bytes = bytes;
        }

        public static Utf8Span Empty { get { return s_empty; } }

        public int Length
        {
            get { return _bytes.Length; }
        }

        public override bool Equals(object obj)
        {
            throw new InvalidOperationException("this should not be called");
        }

        public bool Equals(Utf8String other)
        {
            if (Length != other.Length) return false;
            for(int i=0; i<Length; i++) {
                if (_bytes[i] != other.Bytes[i]) return false;
            }
            return true;
        }

        public override int GetHashCode()
        {
            throw new InvalidOperationException("you don't want it in a hashtable, do you?");
        }
    }

    public enum HttpMethod : byte
    {
        Unknown = 0,
        Get,
        Post,
        Put,
        Delete,
    }

    public enum HttpVersion : byte
    {
        Unknown = 0,
        V1_0,
        V1_1,
        V2_0,
    }

    public struct HttpRequestLine
    {
        public HttpMethod Method;
        public HttpVersion Version;
        public Utf8Span RequestUri;

        public override string ToString()
        {
            return RequestUri.ToString();
        }
    }

    public struct HttpRequestReader
    {
        static readonly Utf8String s_Http1_0 = new Utf8String("HTTP/1.0");
        static readonly Utf8String s_Http1_1 = new Utf8String("HTTP/1.1");
        static readonly Utf8String s_Http2_0 = new Utf8String("HTTP/2.0");

        internal const byte s_SP = 32; // space
        internal const byte s_CR = 13; // carriage return
        internal const byte s_LF = 10; // line feed
        internal const byte s_HT = 9;   // horizontal TAB

        public ByteSpan Buffer;

        public HttpMethod ReadMethod()
        {
            HttpMethod method;
            int parsedBytes;
            if (!HttpRequestParser.TryParseMethod(Buffer, out method, out parsedBytes))
            {
                return HttpMethod.Unknown;
            }
            Buffer = Buffer.Slice(parsedBytes);
            return method;
        }

        public Utf8Span ReadRequestUri()
        {
            Utf8Span requestUri;
            int parsedBytes;
            if (!HttpRequestParser.TryParseRequestUri(Buffer, out requestUri, out parsedBytes))
            {
                return Utf8Span.Empty;
            }
            Buffer = Buffer.Slice(parsedBytes);
            return requestUri;
        }

        Utf8Span ReadHttpVersionAsUtf8String()
        {
            Utf8Span httpVersion;
            int parsedBytes;
            if (!HttpRequestParser.TryParseHttpVersion(Buffer, out httpVersion, out parsedBytes))
            {
                return Utf8Span.Empty;
            }
            Buffer = Buffer.Slice(parsedBytes);
            return httpVersion;
        }

        public HttpVersion ReadHttpVersion()
        {
            ByteSpan oldBuffer = Buffer;
            Utf8Span version = ReadHttpVersionAsUtf8String();

            if (version.Equals(s_Http1_1))
            {
                return HttpVersion.V1_1;
            }
            else if (version.Equals(s_Http2_0))
            {
                return HttpVersion.V2_0;
            }
            else if (version.Equals(s_Http1_0))
            {
                return HttpVersion.V1_0;
            }
            else
            {
                Buffer = oldBuffer;
                return HttpVersion.Unknown;
            }
        }

        public Utf8Span ReadHeader()
        {
{'fraction_non_alphanumeric': 0.07221350078492936, 'fraction_numerical': 0.016181620577224973, 'mean_word_length': 1.5006038647342994, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5993985', 'n_tokens_mistral': 2269, 'n_tokens_neox': 2181, 'n_words': 589}