diff --git a/modules/reitit-core/java-src/reitit/Trie.java b/modules/reitit-core/java-src/reitit/Trie.java index aa12c957..55250fdc 100644 --- a/modules/reitit-core/java-src/reitit/Trie.java +++ b/modules/reitit-core/java-src/reitit/Trie.java @@ -13,8 +13,8 @@ import java.util.*; public class Trie { - private static String decode(char[] chars, int i, int j, boolean hasPercent, boolean hasPlus) { - final String s = new String(chars, i, j); + private static String decode(char[] chars, int offset, int count, boolean hasPercent, boolean hasPlus) { + final String s = new String(chars, offset, count); try { if (hasPercent) { return URLDecoder.decode(hasPlus ? s.replace("+", "%2B") : s, "UTF-8"); @@ -24,6 +24,20 @@ public class Trie { return s; } + private static String decode(char[] chars, int offset, int count) { + boolean hasPercent = false; + boolean hasPlus = false; + for (int j = offset; j < offset + count; j++) { + if (chars[j] == '%') { + hasPercent = true; + } else if (chars[j] == '+') { + hasPlus = true; + } + } + System.err.println(); + return decode(chars, offset, count, hasPercent, hasPlus); + } + public static class Match { final ITransientMap params = PersistentArrayMap.EMPTY.asTransient(); public Object data; @@ -36,7 +50,7 @@ public class Trie { public String toString() { Map m = new HashMap<>(); m.put(Keyword.intern("data"), data); - m.put(Keyword.intern("params"), params.persistent()); + m.put(Keyword.intern("params"), parameters()); return m.toString(); } } @@ -163,6 +177,35 @@ public class Trie { } } + public static CatchAllMatcher catchAllMatcher(Keyword parameter, Object data) { + return new CatchAllMatcher(parameter, data); + } + + static final class CatchAllMatcher implements Matcher { + private final Keyword parameter; + private final Object data; + + CatchAllMatcher(Keyword parameter, Object data) { + this.parameter = parameter; + this.data = data; + } + + @Override + public Match match(int i, Path path, Match match) { + if (i < path.value.length) { + match.params.assoc(parameter, decode(path.value, i, path.size - i)); + match.data = data; + return match; + } + return null; + } + + @Override + public String toString() { + return "[" + parameter + " " + new DataMatcher(data) + "]"; + } + } + public static LinearMatcher linearMatcher(List childs) { return new LinearMatcher(childs); } @@ -198,6 +241,10 @@ public class Trie { return matcher.match(0, new Path(path), new Match()); } + public static Matcher scanner(List matchers) { + return new LinearMatcher(matchers); + } + public static void main(String[] args) { //Matcher matcher = new StaticMatcher("/kikka", new StaticMatcher("/kukka", new DataMatcher(1))); diff --git a/modules/reitit-core/src/reitit/core.cljc b/modules/reitit-core/src/reitit/core.cljc index d6cc99b1..207382a1 100644 --- a/modules/reitit-core/src/reitit/core.cljc +++ b/modules/reitit-core/src/reitit/core.cljc @@ -1,7 +1,6 @@ (ns reitit.core (:require [meta-merge.core :refer [meta-merge]] [clojure.string :as str] - [reitit.segment :as segment] [reitit.trie :as trie] [reitit.impl :as impl #?@(:cljs [:refer [Route]])]) #?(:clj @@ -176,12 +175,12 @@ f #(if-let [path (impl/path-for route %)] (->Match p data result (impl/url-decode-coll %) path) (->PartialMatch p data result % path-params))] - [(conj pl (-> (segment/insert nil p (->Match p data result nil nil)) (segment/compile))) + [(conj pl (-> (trie/insert nil p (->Match p data result nil nil)) (trie/compile))) (if name (assoc nl name f) nl)])) [[] {}] compiled-routes) lookup (impl/fast-map nl) - scanner (segment/scanner pl) + scanner (trie/scanner pl) routes (uncompile-routes compiled-routes)] ^{:type ::router} (reify @@ -197,7 +196,7 @@ (route-names [_] names) (match-by-path [_ path] - (if-let [match (segment/lookup scanner path)] + (if-let [match (trie/lookup scanner path)] (-> (:data match) (assoc :path-params (:path-params match)) (assoc :path path)))) diff --git a/modules/reitit-core/src/reitit/trie.cljc b/modules/reitit-core/src/reitit/trie.cljc index f615a597..7ef8e481 100644 --- a/modules/reitit-core/src/reitit/trie.cljc +++ b/modules/reitit-core/src/reitit/trie.cljc @@ -94,7 +94,8 @@ (let [matchers (cond-> [] data (conj (Trie/dataMatcher data)) children (into (for [[p c] children] (Trie/staticMatcher p (compile c)))) - wilds (into (for [[p c] wilds] (Trie/wildMatcher p (compile c)))))] + wilds (into (for [[p c] wilds] (Trie/wildMatcher p (compile c)))) + catch-all (into (for [[p c] catch-all] (Trie/catchAllMatcher (first p) (:data c)))))] (if (rest matchers) (Trie/linearMatcher matchers) (first matchers)))) @@ -108,6 +109,9 @@ (if-let [match ^Trie$Match (Trie/lookup matcher ^String path)] (->Match (.data match) (.parameters match)))) +(defn scanner [compiled-tries] + (Trie/scanner compiled-tries)) + ;; ;; matcher ;; diff --git a/project.clj b/project.clj index b9e2b8b4..bd289aa4 100644 --- a/project.clj +++ b/project.clj @@ -62,7 +62,7 @@ "modules/reitit-sieppari/src" "modules/reitit-pedestal/src"] - ;:java-source-paths ["modules/reitit-core/java-src"] + :java-source-paths ["modules/reitit-core/java-src"] :dependencies [[org.clojure/clojure "1.10.0"] [org.clojure/clojurescript "1.10.439"]