Functional segemnt-router

This commit is contained in:
Tommi Reiman 2017-11-24 07:34:14 +02:00
parent ec35c2ebbf
commit 102fd35f04
2 changed files with 24 additions and 19 deletions

View file

@ -29,7 +29,7 @@
(defn catch-all-param [s] (defn catch-all-param [s]
(let [ss (str s)] (let [ss (str s)]
(if (= \* (first ss)) (if (= \* (first ss))
(keyword ss)))) (keyword (subs ss 1)))))
(defn wild-or-catch-all-param? [x] (defn wild-or-catch-all-param? [x]
(boolean (or (wild-param x) (catch-all-param x)))) (boolean (or (wild-param x) (catch-all-param x))))

View file

@ -1,5 +1,6 @@
(ns reitit.segment (ns reitit.segment
(:require [reitit.impl :as impl])) (:require [reitit.impl :as impl]
[clojure.string :as str]))
(defrecord Match [data params]) (defrecord Match [data params])
@ -12,41 +13,45 @@
(-insert [this ps data]) (-insert [this ps data])
(-lookup [this ps params])) (-lookup [this ps params]))
;; TODO: catch-all (defn- -catch-all [catch-all data params p ps]
(if catch-all
(assoc data :params (assoc params catch-all (str/join "/" (cons p ps))))))
(defn- segment (defn- segment
([] ([] (segment {} #{} nil nil))
(segment {} #{} nil)) ([children wilds catch-all data]
([children wilds data]
(let [children' (impl/fast-map children)] (let [children' (impl/fast-map children)]
^{:type ::segment}
(reify (reify
Segment Segment
(-insert [_ [p & ps] data] (-insert [_ [p & ps] d]
(if-not p (if-not p
(segment children wilds data) (segment children wilds catch-all d)
(let [wild (impl/wild-param p) (let [[w c] ((juxt impl/wild-param impl/catch-all-param) p)
wilds (if wild (conj wilds wild) wilds) wilds (if w (conj wilds w) wilds)
children (update children (or wild p) #(-insert (or % (segment)) ps data))] catch-all (or c catch-all)
(segment children wilds nil)))) children (update children (or w c p) #(-insert (or % (segment)) ps d))]
(segment children wilds catch-all data))))
(-lookup [_ [p & ps] params] (-lookup [_ [p & ps] params]
(if (nil? p) (if (nil? p)
(if data (assoc data :params params)) (if data (assoc data :params params))
(or (-lookup (impl/fast-get children' p) ps params) (or (-lookup (impl/fast-get children' p) ps params)
(some #(-lookup (impl/fast-get children' %) ps (assoc params % p)) wilds)))))))) (some #(-lookup (impl/fast-get children' %) ps (assoc params % p)) wilds)
(-catch-all catch-all data params p ps))))))))
(defn create [paths] (defn create [paths]
(reduce (reduce
(fn [segment [p data]] (fn [segment [p data]]
(let [ps (impl/segments p)] (-insert segment (impl/segments p) (map->Match {:data data})))
(-insert segment ps (map->Match {:data data}))))
(segment) paths)) (segment) paths))
(defn lookup [segment ^String path] (defn lookup [segment ^String path]
(let [ps (.split path "/")] (-lookup segment (.split path "/") {}))
(-lookup segment ps {})))
(comment (comment
(-> [["/:abba" 1] (-> [["/:abba" 1]
["/kikka/*kakka" 2]] ["/:abba/:dabba" 2]
["/kikka/*kakka" 3]]
(create) (create)
(lookup "/kikka") (lookup "/kikka/1/2")
(./aprint))) (./aprint)))