This commit is contained in:
Tommi Reiman 2019-01-13 21:25:25 +02:00
parent 93bcc5dad8
commit 5079daa8f3
6 changed files with 35 additions and 30 deletions

View file

@ -3,7 +3,7 @@ package reitit;
import clojure.lang.Keyword; import clojure.lang.Keyword;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLDecoder;
import java.util.*; import java.util.*;
public class SegmentTrie { public class SegmentTrie {
@ -30,7 +30,7 @@ public class SegmentTrie {
if (s.contains("+")) { if (s.contains("+")) {
_s = s.replace("+", "%2B"); _s = s.replace("+", "%2B");
} }
return URLEncoder.encode(_s, "UTF-8"); return URLDecoder.decode(_s, "UTF-8");
} }
} catch (UnsupportedEncodingException ignored) { } catch (UnsupportedEncodingException ignored) {
} }
@ -72,6 +72,7 @@ public class SegmentTrie {
SegmentTrie s = pointer.catchAll.get(k); SegmentTrie s = pointer.catchAll.get(k);
if (s == null) { if (s == null) {
s = new SegmentTrie(); s = new SegmentTrie();
s.data = data;
pointer.catchAll.put(k, s); pointer.catchAll.put(k, s);
} }
break; break;
@ -103,7 +104,7 @@ public class SegmentTrie {
public Matcher matcher() { public Matcher matcher() {
Matcher m; Matcher m;
if (!catchAll.isEmpty()) { if (!catchAll.isEmpty()) {
m = new CatchAllMatcher(catchAll.keySet().iterator().next(), catchAll.values().iterator().next().data); m = new CatchAllMatcher(catchAll.keySet().iterator().next(), data);
} else if (!wilds.isEmpty()) { } else if (!wilds.isEmpty()) {
List<Matcher> matchers = new ArrayList<>(); List<Matcher> matchers = new ArrayList<>();
if (data != null) { if (data != null) {
@ -118,12 +119,12 @@ public class SegmentTrie {
m = new LinearMatcher(matchers); m = new LinearMatcher(matchers);
} else if (!childs.isEmpty()) { } else if (!childs.isEmpty()) {
m = staticMatcher(); m = staticMatcher();
if (data != null) {
m = new LinearMatcher(Arrays.asList(new DataMatcher(data), m));
}
} else { } else {
return new DataMatcher(data); return new DataMatcher(data);
} }
if (data != null) {
m = new LinearMatcher(Arrays.asList(new DataMatcher(data), m));
}
return m; return m;
} }
@ -165,10 +166,12 @@ public class SegmentTrie {
@Override @Override
public Match match(int i, List<String> segments, Match match) { public Match match(int i, List<String> segments, Match match) {
final Match m = child.match(i + 1, segments, match); if (i < segments.size() && !segments.get(i).isEmpty()) {
if (m != null) { final Match m = child.match(i + 1, segments, match);
m.params.put(parameter, encode(segments.get(i))); if (m != null) {
return m; m.params.put(parameter, encode(segments.get(i)));
return m;
}
} }
return null; return null;
} }
@ -294,7 +297,7 @@ public class SegmentTrie {
Map<String, Matcher> m2 = new HashMap<>(); Map<String, Matcher> m2 = new HashMap<>();
m2.put("user", new WildMatcher(Keyword.intern("id"), new StaticMapMatcher(m1))); m2.put("user", new WildMatcher(Keyword.intern("id"), new StaticMapMatcher(m1)));
m2.put("company", new WildMatcher(Keyword.intern("cid"), new StaticMatcher("dept", new WildMatcher(Keyword.intern("did"), new DataMatcher(3))))); m2.put("company", new WildMatcher(Keyword.intern("cid"), new StaticMatcher("dept", new WildMatcher(Keyword.intern("did"), new DataMatcher(3)))));
m2.put("public", new CatchAllMatcher(Keyword.intern("*"), 4)); m2.put("public", new CatchAllMatcher(Keyword.intern("*"), new DataMatcher(4)));
m2.put("kikka", new LinearMatcher(Arrays.asList(new StaticMatcher("ping", new DataMatcher(5)), new WildMatcher(Keyword.intern("id"), new StaticMatcher("ping", new DataMatcher(6)))))); m2.put("kikka", new LinearMatcher(Arrays.asList(new StaticMatcher("ping", new DataMatcher(5)), new WildMatcher(Keyword.intern("id"), new StaticMatcher("ping", new DataMatcher(6))))));
return new StaticMapMatcher(m2); return new StaticMapMatcher(m2);
} }
@ -302,14 +305,14 @@ public class SegmentTrie {
public static void main(String[] args) { public static void main(String[] args) {
SegmentTrie trie = new SegmentTrie(); SegmentTrie trie = new SegmentTrie();
//trie.add("/kikka/:id/permissions", 1); trie.add("/:abba", 1);
trie.add("/kikka/:id", 2); trie.add("/abba/1", 2);
trie.add("/kakka/ping", 3); trie.add("/:abba/:dabba/doo", 3);
trie.add("/abba/:dabba/boo", 4);
Matcher m = trie.matcher(); Matcher m = trie.matcher();
System.err.println(m); System.err.println(m);
System.out.println(lookup(m, "/kikka/1/permissions")); System.err.println(m.getClass());
System.out.println(lookup(m, "/kikka/1")); System.out.println(lookup(m, "/abba"));
/* /*
SegmentTrie trie = new SegmentTrie(); SegmentTrie trie = new SegmentTrie();
trie.add("/user/:id/profile/:type", 1); trie.add("/user/:id/profile/:type", 1);

View file

@ -289,7 +289,9 @@
names) names)
(match-by-path [_ path] (match-by-path [_ path]
(if-let [match (segment/lookup pl path)] (if-let [match (segment/lookup pl path)]
(assoc (:data match) :path path))) (-> (:data match)
(assoc :path-params (:path-params match))
(assoc :path path))))
(match-by-name [_ name] (match-by-name [_ name]
(if-let [match (impl/fast-get lookup name)] (if-let [match (impl/fast-get lookup name)]
(match nil))) (match nil)))

View file

@ -2,7 +2,7 @@
(:refer-clojure :exclude [-lookup compile]) (:refer-clojure :exclude [-lookup compile])
(:require [reitit.impl :as impl] (:require [reitit.impl :as impl]
[clojure.string :as str]) [clojure.string :as str])
#?(:clj (:import (reitit SegmentTrie Trie$Match)))) #?(:clj (:import (reitit SegmentTrie SegmentTrie$Match))))
(defrecord Match [data path-params]) (defrecord Match [data path-params])
@ -54,9 +54,9 @@
(defn compile [segment] (defn compile [segment]
#?(:cljs segment #?(:cljs segment
:clj (.matcher ^SegmentTrie segment))) :clj (.matcher ^SegmentTrie (or segment (SegmentTrie.)))))
(defn lookup [segment path] (defn lookup [segment path]
#?(:cljs (-lookup segment (impl/segments path) {}) #?(:cljs (-lookup segment (impl/segments path) {})
:clj (if-let [match ^Trie$Match (SegmentTrie/lookup segment path)] :clj (if-let [match ^SegmentTrie$Match (SegmentTrie/lookup segment path)]
(->Match (.data match) (clojure.lang.PersistentHashMap/create (.params match)))))) (->Match (.data match) (clojure.lang.PersistentHashMap/create (.params match))))))

View file

@ -144,7 +144,7 @@
request (enrich-request request path-params match router)] request (enrich-request request path-params match router)]
(or (interceptor/execute executor interceptors request) (or (interceptor/execute executor interceptors request)
(interceptor/execute executor default-queue request))) (interceptor/execute executor default-queue request)))
(interceptor/execute executor default-queue (enrich-default-request request)))) (interceptor/execute executor default-queue (enrich-default-request request router))))
([request respond raise] ([request respond raise]
(let [default #(interceptor/execute executor default-queue % respond raise)] (let [default #(interceptor/execute executor default-queue % respond raise)]
(if-let [match (r/match-by-path router (:uri request))] (if-let [match (r/match-by-path router (:uri request))]
@ -160,7 +160,7 @@
(if interceptors (if interceptors
(interceptor/execute executor interceptors request respond' raise) (interceptor/execute executor interceptors request respond' raise)
(default request))) (default request)))
(default (enrich-default-request request)))) (default (enrich-default-request request router))))
nil)) nil))
{::r/router router})))) {::r/router router}))))

View file

@ -285,7 +285,7 @@
handler (-> result method :handler (or default-handler)) handler (-> result method :handler (or default-handler))
request (enrich-request request path-params match router)] request (enrich-request request path-params match router)]
(or (handler request) (default-handler request))) (or (handler request) (default-handler request)))
(default-handler (enrich-default-request request)))) (default-handler (enrich-default-request request router))))
([request respond raise] ([request respond raise]
(if-let [match (r/match-by-path router (:uri request))] (if-let [match (r/match-by-path router (:uri request))]
(let [method (:request-method request) (let [method (:request-method request)
@ -294,7 +294,7 @@
handler (-> result method :handler (or default-handler)) handler (-> result method :handler (or default-handler))
request (enrich-request request path-params match router)] request (enrich-request request path-params match router)]
((routes handler default-handler) request respond raise)) ((routes handler default-handler) request respond raise))
(default-handler (enrich-default-request request) respond raise)) (default-handler (enrich-default-request request router) respond raise))
nil))) nil)))
{::r/router router})))) {::r/router router}))))

View file

@ -7,7 +7,7 @@
[reitit.impl :as impl] [reitit.impl :as impl]
[reitit.ring :as ring] [reitit.ring :as ring]
[reitit.core :as r]) [reitit.core :as r])
(:import (reitit SegmentTrie Trie$Matcher) (:import (reitit SegmentTrie SegmentTrie$Matcher)
(calfpath Util))) (calfpath Util)))
;; ;;
@ -120,7 +120,7 @@
(cc/quick-bench (cc/quick-bench
(r/match-by-path router "/user/1234/profile/compact")))) (r/match-by-path router "/user/1234/profile/compact"))))
(let [lookup ^Trie$Matcher (SegmentTrie/sample)] (let [lookup ^SegmentTrie$Matcher (SegmentTrie/sample)]
(SegmentTrie/lookup lookup "/user/1234/profile/compact") (SegmentTrie/lookup lookup "/user/1234/profile/compact")
#_(cc/quick-bench #_(cc/quick-bench
(SegmentTrie/lookup lookup "/user/1234/profile/compact"))) (SegmentTrie/lookup lookup "/user/1234/profile/compact")))
@ -172,20 +172,20 @@
(comment (comment
(let [matcher ^Trie$Matcher (SegmentTrie/sample)] (let [matcher ^SegmentTrie$Matcher (SegmentTrie/sample)]
(SegmentTrie/lookup matcher "/user/1234/profile/compact") (SegmentTrie/lookup matcher "/user/1234/profile/compact")
(cc/quick-bench (cc/quick-bench
(SegmentTrie/lookup matcher "/user/1234/profile/compact"))) (SegmentTrie/lookup matcher "/user/1234/profile/compact")))
;; 173ns ;; 173ns
(let [lookup ^Trie$Matcher (SegmentTrie/tree2)] (let [lookup ^SegmentTrie$Matcher (SegmentTrie/tree2)]
(SegmentTrie/lookup lookup "/user/1234/profile/compact") (SegmentTrie/lookup lookup "/user/1234/profile/compact")
(cc/quick-bench (cc/quick-bench
(SegmentTrie/lookup lookup "/user/1234/profile/compact"))) (SegmentTrie/lookup lookup "/user/1234/profile/compact")))
;; 140ns ;; 140ns
(let [lookup ^Trie$Matcher (SegmentTrie/tree1)] (let [lookup ^SegmentTrie$Matcher (SegmentTrie/tree1)]
(SegmentTrie/lookup lookup "/user/1234/profile/compact") (SegmentTrie/lookup lookup "/user/1234/profile/compact")
(cc/quick-bench (cc/quick-bench
(SegmentTrie/lookup lookup "/user/1234/profile/compact"))) (SegmentTrie/lookup lookup "/user/1234/profile/compact")))