mirror of
https://github.com/metosin/reitit.git
synced 2025-12-18 00:41:12 +00:00
cljs trie
This commit is contained in:
parent
5b9f90d283
commit
54d5550fae
1 changed files with 117 additions and 115 deletions
|
|
@ -1,8 +1,8 @@
|
|||
(ns reitit.trie
|
||||
(:refer-clojure :exclude [compile])
|
||||
(:refer-clojure :exclude [compile -assoc!])
|
||||
(:require [clojure.string :as str])
|
||||
(:import [reitit Trie Trie$Match Trie$Matcher]
|
||||
(java.net URLDecoder)))
|
||||
#?(:clj (:import [reitit Trie Trie$Match Trie$Matcher]
|
||||
(java.net URLDecoder))))
|
||||
|
||||
(defrecord Wild [value])
|
||||
(defrecord CatchAll [value])
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
(defn catch-all? [x] (instance? CatchAll x))
|
||||
|
||||
(defprotocol Matcher
|
||||
(match [this i max ^chars path])
|
||||
(match [this i max path])
|
||||
(view [this])
|
||||
(depth [this]))
|
||||
|
||||
|
|
@ -116,27 +116,27 @@
|
|||
(update :children dissoc ""))
|
||||
node')))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(defn decode!
|
||||
([chars start end]
|
||||
(let [s (String. ^chars chars ^int start ^int (- end start))]
|
||||
(if (str/index-of s \%)
|
||||
(URLDecoder/decode
|
||||
(if (str/index-of s \+) (.replace ^String s "+" "%2B") s)
|
||||
"UTF-8")
|
||||
s)))
|
||||
([chars start end percent? plus?]
|
||||
(let [s (String. ^chars chars ^int start ^int (- end start))]
|
||||
(if percent?
|
||||
(URLDecoder/decode
|
||||
(if plus? (.replace ^String s "+" "%2B") s)
|
||||
"UTF-8")
|
||||
s))))
|
||||
([path start end]
|
||||
#?(:clj (let [s (subs path start end)]
|
||||
(if (str/index-of s \%)
|
||||
(URLDecoder/decode
|
||||
(if (str/index-of s \+) (.replace ^String s "+" "%2B") s)
|
||||
"UTF-8")
|
||||
s))
|
||||
:cljs (js/decodeURIComponent (subs path start end))))
|
||||
([path start end percent? plus?]
|
||||
#?(:clj (let [s (String. ^chars path ^int start ^int (- end start))]
|
||||
(if percent?
|
||||
(URLDecoder/decode
|
||||
(if plus? (.replace ^String s "+" "%2B") s)
|
||||
"UTF-8")
|
||||
s))
|
||||
:cljs (js/decodeURIComponent (subs path start end)))))
|
||||
|
||||
(defn data-matcher [data]
|
||||
#?(:cljx (Trie/dataMatcher data)
|
||||
:clj (let [match (->Match data nil)]
|
||||
#?(:clj (Trie/dataMatcher data)
|
||||
:cljs (let [match (->Match data nil)]
|
||||
(reify Matcher
|
||||
(match [_ i max _]
|
||||
(if (= i max)
|
||||
|
|
@ -144,31 +144,30 @@
|
|||
(view [_] data)
|
||||
(depth [_] 1)))))
|
||||
|
||||
(defn static-matcher [^String path matcher]
|
||||
#?(:cljx (Trie/staticMatcher path matcher)
|
||||
:clj (let [^chars chars (.toCharArray path)
|
||||
size (alength chars)]
|
||||
(defn static-matcher [path matcher]
|
||||
#?(:clj (Trie/staticMatcher ^String path ^Trie$Matcher matcher)
|
||||
:cljs (let [size (count path)]
|
||||
(reify Matcher
|
||||
(match [_ i max path]
|
||||
(if-not (< max (+ ^int i size))
|
||||
(match [_ i max p]
|
||||
(if-not (< max (+ i size))
|
||||
(loop [j 0]
|
||||
(if (= j size)
|
||||
(match matcher (+ ^int i size) max path)
|
||||
(if (= ^char (aget ^chars path (+ ^int i j)) ^char (aget ^chars chars j))
|
||||
(match matcher (+ i size) max p)
|
||||
(if (= (get p (+ i j)) (get path j))
|
||||
(recur (inc j)))))))
|
||||
(view [_] [path (view matcher)])
|
||||
(depth [_] (inc (depth matcher)))))))
|
||||
|
||||
(defn wild-matcher [key matcher]
|
||||
#?(:cljx (Trie/wildMatcher key matcher)
|
||||
:clj (reify Matcher
|
||||
#?(:clj (Trie/wildMatcher key matcher)
|
||||
:cljs (reify Matcher
|
||||
(match [_ i max path]
|
||||
(if (and (< ^int i ^int max) (not= ^char (aget ^chars path i) \/))
|
||||
(loop [percent? false, plus? false, ^int j ^int i]
|
||||
(if (= ^int max j)
|
||||
(if (and (< i max) (not= (get path i) \/))
|
||||
(loop [percent? false, plus? false, j i]
|
||||
(if (= max j)
|
||||
(if-let [match (match matcher max max path)]
|
||||
(-assoc! match key (decode! path i max percent? plus?)))
|
||||
(let [c ^char (aget ^chars path j)]
|
||||
(let [c ^char (get path j)]
|
||||
(case c
|
||||
\/ (if-let [match (match matcher j max path)]
|
||||
(-assoc! match key (decode! path i j percent? plus?)))
|
||||
|
|
@ -179,24 +178,24 @@
|
|||
(depth [_] (inc (depth matcher))))))
|
||||
|
||||
(defn catch-all-matcher [key data]
|
||||
#?(:cljx (Trie/catchAllMatcher key data)
|
||||
:clj (let [match (->Match data nil)]
|
||||
#?(:clj (Trie/catchAllMatcher key data)
|
||||
:cljs (let [match (->Match data nil)]
|
||||
(reify Matcher
|
||||
(match [_ i max path]
|
||||
(if (< ^int i max)
|
||||
(if (< i max)
|
||||
(-assoc! match key (decode! path i max))))
|
||||
(view [_] [key [data]])
|
||||
(depth [_] 1)))))
|
||||
|
||||
(defn linear-matcher [matchers]
|
||||
#?(:cljx (Trie/linearMatcher matchers)
|
||||
:clj (let [matchers (.toArray ^java.util.List (reverse (sort-by depth matchers)))
|
||||
size (alength matchers)]
|
||||
#?(:clj (Trie/linearMatcher matchers)
|
||||
:cljs (let [matchers (vec (reverse (sort-by depth matchers)))
|
||||
size (count matchers)]
|
||||
(reify Matcher
|
||||
(match [_ i max path]
|
||||
(loop [j 0]
|
||||
(if (< j size)
|
||||
(or (match (aget matchers j) i max path)
|
||||
(or (match (get matchers j) i max path)
|
||||
(recur (inc j))))))
|
||||
(view [_] (mapv view matchers))
|
||||
(depth [_] (apply max (map depth matchers)))))))
|
||||
|
|
@ -227,85 +226,88 @@
|
|||
(first matchers))))
|
||||
|
||||
(defn pretty [matcher]
|
||||
#?(:cljx (-> matcher str read-string eval)
|
||||
:clj (view matcher)))
|
||||
#?(:clj (-> matcher str read-string eval)
|
||||
:cljs (view matcher)))
|
||||
|
||||
(defn lookup [matcher ^String path]
|
||||
#?(:cljx (if-let [match ^Trie$Match (Trie/lookup ^Trie$Matcher matcher ^String path)]
|
||||
(defn lookup [matcher path]
|
||||
#?(:clj (if-let [match ^Trie$Match (Trie/lookup ^Trie$Matcher matcher ^String path)]
|
||||
(->Match (.data match) (.parameters match)))
|
||||
:clj (let [chars (.toCharArray path)]
|
||||
(if-let [match (match matcher 0 (alength chars) chars)]
|
||||
(let [params (if-let [path-params (:path-params match)]
|
||||
(persistent! path-params)
|
||||
{})]
|
||||
(assoc match :path-params params))))))
|
||||
:cljs (if-let [match (match matcher 0 (count path) path)]
|
||||
(let [params (if-let [path-params (:path-params match)]
|
||||
(persistent! path-params)
|
||||
{})]
|
||||
(assoc match :path-params params)))))
|
||||
|
||||
;;
|
||||
;; spike
|
||||
;;
|
||||
|
||||
(->
|
||||
[["/v2/whoami" 1]
|
||||
["/v2/users/:user-id/datasets" 2]
|
||||
["/v2/public/projects/:project-id/datasets" 3]
|
||||
["/v1/public/topics/:topic" 4]
|
||||
["/v1/users/:user-id/orgs/:org-id" 5]
|
||||
["/v1/search/topics/:term" 6]
|
||||
["/v1/users/:user-id/invitations" 7]
|
||||
["/v1/users/:user-id/topics" 9]
|
||||
["/v1/users/:user-id/bookmarks/followers" 10]
|
||||
["/v2/datasets/:dataset-id" 11]
|
||||
["/v1/orgs/:org-id/usage-stats" 12]
|
||||
["/v1/orgs/:org-id/devices/:client-id" 13]
|
||||
["/v1/messages/user/:user-id" 14]
|
||||
["/v1/users/:user-id/devices" 15]
|
||||
["/v1/public/users/:user-id" 16]
|
||||
["/v1/orgs/:org-id/errors" 17]
|
||||
["/v1/public/orgs/:org-id" 18]
|
||||
["/v1/orgs/:org-id/invitations" 19]
|
||||
["/v1/users/:user-id/device-errors" 22]
|
||||
["/v2/login" 23]
|
||||
["/v1/users/:user-id/usage-stats" 24]
|
||||
["/v2/users/:user-id/devices" 25]
|
||||
["/v1/users/:user-id/claim-device/:client-id" 26]
|
||||
["/v2/public/projects/:project-id" 27]
|
||||
["/v2/public/datasets/:dataset-id" 28]
|
||||
["/v2/users/:user-id/topics/bulk" 29]
|
||||
["/v1/messages/device/:client-id" 30]
|
||||
["/v1/users/:user-id/owned-orgs" 31]
|
||||
["/v1/topics/:topic" 32]
|
||||
["/v1/users/:user-id/bookmark/:topic" 33]
|
||||
["/v1/orgs/:org-id/members/:user-id" 34]
|
||||
["/v1/users/:user-id/devices/:client-id" 35]
|
||||
["/v1/users/:user-id" 36]
|
||||
["/v1/orgs/:org-id/devices" 37]
|
||||
["/v1/orgs/:org-id/members" 38]
|
||||
["/v2/orgs/:org-id/topics" 40]
|
||||
["/v1/whoami" 41]
|
||||
["/v1/orgs/:org-id" 42]
|
||||
["/v1/users/:user-id/api-key" 43]
|
||||
["/v2/schemas" 44]
|
||||
["/v2/users/:user-id/topics" 45]
|
||||
["/v1/orgs/:org-id/confirm-membership/:token" 46]
|
||||
["/v2/topics/:topic" 47]
|
||||
["/v1/messages/topic/:topic" 48]
|
||||
["/v1/users/:user-id/devices/:client-id/reset-password" 49]
|
||||
["/v2/topics" 50]
|
||||
["/v1/login" 51]
|
||||
["/v1/users/:user-id/orgs" 52]
|
||||
["/v2/public/messages/dataset/:dataset-id" 53]
|
||||
["/v1/topics" 54]
|
||||
["/v1/orgs" 55]
|
||||
["/v1/users/:user-id/bookmarks" 56]
|
||||
["/v1/orgs/:org-id/topics" 57]]
|
||||
(insert)
|
||||
(compile)
|
||||
(pretty))
|
||||
|
||||
(-> [["/kikka" 2]
|
||||
["/kikka/kakka/kukka" 3]
|
||||
["/kikka/:kakka/kurkku" 4]
|
||||
["/kikka/kuri/{user/doc}/html" 5]]
|
||||
(comment
|
||||
(->
|
||||
[["/v2/whoami" 1]
|
||||
["/v2/users/:user-id/datasets" 2]
|
||||
["/v2/public/projects/:project-id/datasets" 3]
|
||||
["/v1/public/topics/:topic" 4]
|
||||
["/v1/users/:user-id/orgs/:org-id" 5]
|
||||
["/v1/search/topics/:term" 6]
|
||||
["/v1/users/:user-id/invitations" 7]
|
||||
["/v1/users/:user-id/topics" 9]
|
||||
["/v1/users/:user-id/bookmarks/followers" 10]
|
||||
["/v2/datasets/:dataset-id" 11]
|
||||
["/v1/orgs/:org-id/usage-stats" 12]
|
||||
["/v1/orgs/:org-id/devices/:client-id" 13]
|
||||
["/v1/messages/user/:user-id" 14]
|
||||
["/v1/users/:user-id/devices" 15]
|
||||
["/v1/public/users/:user-id" 16]
|
||||
["/v1/orgs/:org-id/errors" 17]
|
||||
["/v1/public/orgs/:org-id" 18]
|
||||
["/v1/orgs/:org-id/invitations" 19]
|
||||
["/v1/users/:user-id/device-errors" 22]
|
||||
["/v2/login" 23]
|
||||
["/v1/users/:user-id/usage-stats" 24]
|
||||
["/v2/users/:user-id/devices" 25]
|
||||
["/v1/users/:user-id/claim-device/:client-id" 26]
|
||||
["/v2/public/projects/:project-id" 27]
|
||||
["/v2/public/datasets/:dataset-id" 28]
|
||||
["/v2/users/:user-id/topics/bulk" 29]
|
||||
["/v1/messages/device/:client-id" 30]
|
||||
["/v1/users/:user-id/owned-orgs" 31]
|
||||
["/v1/topics/:topic" 32]
|
||||
["/v1/users/:user-id/bookmark/:topic" 33]
|
||||
["/v1/orgs/:org-id/members/:user-id" 34]
|
||||
["/v1/users/:user-id/devices/:client-id" 35]
|
||||
["/v1/users/:user-id" 36]
|
||||
["/v1/orgs/:org-id/devices" 37]
|
||||
["/v1/orgs/:org-id/members" 38]
|
||||
["/v2/orgs/:org-id/topics" 40]
|
||||
["/v1/whoami" 41]
|
||||
["/v1/orgs/:org-id" 42]
|
||||
["/v1/users/:user-id/api-key" 43]
|
||||
["/v2/schemas" 44]
|
||||
["/v2/users/:user-id/topics" 45]
|
||||
["/v1/orgs/:org-id/confirm-membership/:token" 46]
|
||||
["/v2/topics/:topic" 47]
|
||||
["/v1/messages/topic/:topic" 48]
|
||||
["/v1/users/:user-id/devices/:client-id/reset-password" 49]
|
||||
["/v2/topics" 50]
|
||||
["/v1/login" 51]
|
||||
["/v1/users/:user-id/orgs" 52]
|
||||
["/v2/public/messages/dataset/:dataset-id" 53]
|
||||
["/v1/topics" 54]
|
||||
["/v1/orgs" 55]
|
||||
["/v1/users/:user-id/bookmarks" 56]
|
||||
["/v1/orgs/:org-id/topics" 57]]
|
||||
(insert)
|
||||
(compile)
|
||||
(pretty))
|
||||
|
||||
(-> [["/kikka" 2]
|
||||
["/kikka/kakka/kukka" 3]
|
||||
["/kikka/:kakka/kurkku" 4]
|
||||
["/kikka/kuri/{user/doc}/html" 5]]
|
||||
(insert)
|
||||
(compile)
|
||||
(pretty))
|
||||
|
||||
(map str (.toCharArray "\u2215\u0048\u0065\u006C\u006C\u006F"))
|
||||
(count ["∕" "H" "e" "l" "l" "o" " " "W" "o" "r" "l" "d"]))
|
||||
|
|
|
|||
Loading…
Reference in a new issue