1 # Match an HTTP method and path to a handler. Source: https://github.com/paymog/bend-kit/tree/main/router 2 import Base 3 4 # route(wantMethod, gotMethod, "/users/:id", path) → Maybe params. 5 6 def segs.one.if(h: String, acc: List<&2, String>, empty: Bool) -> List<&2, String>: 7 match empty: 8 case True{}: 9 acc 10 case False{}: 11 h <> acc 12 13 def segs.one(+h: String, acc: List<&2, String>) -> List<&2, String>: 14 segs.one.if(h, acc, String.is_empty(h)) 15 16 def segs.keep(xs: List<&2, String>, acc: List<&2, String>) -> List<&2, String>: 17 match xs: 18 case Nil{}: 19 acc 20 case Con{h, t}: 21 segs.keep(t, segs.one(h, acc)) 22 23 def segs(s: String) -> List<&2, String>: 24 segs.keep(String.split(s, '/'), Nil{}) 25 26 def param(+seg: String) -> Bool: 27 String.starts_with(seg, ":") 28 29 @unsafe 30 def zip(pat: List<&2, String>, got: List<&2, String>, +m: Map<&2, String>) -> Maybe<&2, Map<&2, String>>: 31 match pat: 32 case Nil{}: 33 match got: 34 case Nil{}: 35 Some{m} 36 case Con{h, t}: 37 None{} 38 case Con{+p, +pt}: 39 match got: 40 case Nil{}: 41 None{} 42 case Con{+g, +gt}: 43 Bool.pick(Maybe<&2, Map<&2, String>>, param(p), zip(pt, gt, Map.set(&2, String, m, String.drop(p, 1n), g)), Bool.pick(Maybe<&2, Map<&2, String>>, String.eq(p, g), zip(pt, gt, m), None{})) 44 45 def route.ok(pattern: String, path: String, same: Bool) -> Maybe<&2, Map<&2, String>>: 46 match same: 47 case False{}: 48 None{} 49 case True{}: 50 zip(segs(pattern), segs(path), Map.new(&2, String)) 51 52 def route(want: String, method: String, pattern: String, path: String) -> Maybe<&2, Map<&2, String>>: 53 route.ok(pattern, path, String.eq(want, method))