<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Owin.Types;

namespace OwinDispatcher
{
    public class Dispatcher
    {
        private readonly Func<IDictionary<string, object>, Task> _next;
        readonly IDictionary<string, List<Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>>> _handlers;

        public Dispatcher(Func<IDictionary<string, object>, Task> next, Action<Dispatcher> dispatch)
        {
            _next = next;
            _handlers = new Dictionary<string, List<Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>>>();

            dispatch(this);
        }

        private void AddHandler(string method, Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>> handler)
        {
            var key = method.ToLowerInvariant();

            EnsureHandlersHaveMethodKey(key);

            _handlers[key].Add(handler);
        }

        static Regex CreateRegexForUrlPattern(string urlPattern)
        {
            return new Regex(String.Concat("^", urlPattern, "$"));
        }

        void EnsureHandlersHaveMethodKey(string method)
        {
            var key = method.ToLowerInvariant();

            if (!_handlers.ContainsKey(key))
                _handlers.Add(key, new List<Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>>());
        }

        Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> FindHandler(string method, string path)
        {
            var key = method.ToLowerInvariant();
            
            EnsureHandlersHaveMethodKey(key);

            var match = _handlers[key]
                .FirstOrDefault(x => x.Item1.IsMatch(path));

            if (match == null)
                return null;

            return match.Item2;
        }

        public void Get(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "GET", 
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern), 
                    handler));
        }

        public Task Invoke(IDictionary<string, object> environment)
        {
            var request = new OwinRequest(environment);

            var handler = FindHandler(request.Method, request.Path);

            if (handler == null)
                return _next(environment);

            return handler(environment, _next);
        }

        public void Post(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "POST",
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern),
                    handler));
        }
    }
}<commit_msg>add Put, Patch, and Delete to Dispatcher<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Owin.Types;

namespace OwinDispatcher
{
    public class Dispatcher
    {
        private readonly Func<IDictionary<string, object>, Task> _next;
        readonly IDictionary<string, List<Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>>> _handlers;

        public Dispatcher(Func<IDictionary<string, object>, Task> next, Action<Dispatcher> dispatch)
        {
            _next = next;
            _handlers = new Dictionary<string, List<Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>>>();

            dispatch(this);
        }

        private void AddHandler(string method, Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>> handler)
        {
            var key = method.ToLowerInvariant();

            EnsureHandlersHaveMethodKey(key);

            _handlers[key].Add(handler);
        }

        static Regex CreateRegexForUrlPattern(string urlPattern)
        {
            return new Regex(String.Concat("^", urlPattern, "$"));
        }

        public void Delete(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "DELETE",
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern),
                    handler));
        }

        void EnsureHandlersHaveMethodKey(string method)
        {
            var key = method.ToLowerInvariant();

            if (!_handlers.ContainsKey(key))
                _handlers.Add(key, new List<Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>>());
        }

        Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> FindHandler(string method, string path)
        {
            var key = method.ToLowerInvariant();
            
            EnsureHandlersHaveMethodKey(key);

            var match = _handlers[key]
                .FirstOrDefault(x => x.Item1.IsMatch(path));

            if (match == null)
                return null;

            return match.Item2;
        }

        public void Get(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "GET", 
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern), 
                    handler));
        }

        public Task Invoke(IDictionary<string, object> environment)
        {
            var request = new OwinRequest(environment);

            var handler = FindHandler(request.Method, request.Path);

            if (handler == null)
                return _next(environment);

            return handler(environment, _next);
        }

        public void Patch(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "PATCH",
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern),
                    handler));
        }

        public void Post(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "POST",
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern),
                    handler));
        }

        public void Put(
            string urlPattern,
            Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task> handler)
        {
            AddHandler(
                "PUT",
                new Tuple<Regex, Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>(
                    CreateRegexForUrlPattern(urlPattern),
                    handler));
        }
    }
}
{'fraction_non_alphanumeric': 0.10768245838668374, 'fraction_numerical': 0.0005121638924455825, 'mean_word_length': 2.1649108589951376, 'pattern_counts': {'":': 0, '<': 136, '<?xml version=': 0, '>': 138, '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': '7560675', 'n_tokens_mistral': 2077, 'n_tokens_neox': 1984, 'n_words': 458}