~/bend-docscommunity

url.bend source

url.bend on the hub · documented module

import Base# origin-form /path[?k=v] with RFC 3986 percent-encoding.type Url is Data:  Url{path: String, query: Map<&2, String>}def unreserved(+c: U32) -> Bool:  Bool.or(Bool.and(U32.is_le(65, c), U32.is_le(c, 90)), Bool.or(Bool.and(U32.is_le(97, c), U32.is_le(c, 122)), Bool.or(Bool.and(U32.is_le(48, c), U32.is_le(c, 57)), Bool.or(U32.is_eq(c, 45), Bool.or(U32.is_eq(c, 46), Bool.or(U32.is_eq(c, 95), U32.is_eq(c, 126)))))))def path_ok(+c: U32) -> Bool:  Bool.or(unreserved(c), U32.is_eq(c, 47))def hexn(+n: U32) -> U32:  Bool.pick(U32, U32.is_le(n, 9), (48 + n : U32), (55 + n : U32))@unsafedef hexhi.go(+n: U32, +acc: U32, small: Bool) -> U32:  match small:    case True{}:      acc    case False{}:      hexhi.go((n - 16 : U32), (acc + 1 : U32), U32.is_le((n - 16 : U32), 15))def hexhi(+n: U32) -> U32:  hexhi.go(n, 0, U32.is_le(n, 15))def hexlo(+n: U32) -> U32:  (n - (hexhi(n) * 16 : U32) : U32)def pct.enc.push(+c: U32, acc: String, keep: Bool) -> String:  match keep:    case True{}:      SCon{Chr{c}, acc}    case False{}:      SCon{Chr{hexn(hexlo(c))}, SCon{Chr{hexn(hexhi(c))}, SCon{Chr{37}, acc}}}def pct.enc.path(s: String, acc: String) -> String:  match s:    case SNil{}:      String.reverse(acc)    case SCon{Chr{+c}, t}:      pct.enc.path(t, pct.enc.push(c, acc, path_ok(c)))def pct.enc.query(s: String, acc: String) -> String:  match s:    case SNil{}:      String.reverse(acc)    case SCon{Chr{+c}, t}:      pct.enc.query(t, pct.enc.push(c, acc, unreserved(c)))def pct.encode_path(s: String) -> String:  pct.enc.path(s, SNil{})def pct.encode_q(s: String) -> String:  pct.enc.query(s, SNil{})def unhex.H(c: U32, hex: Bool) -> Maybe<&2, U32>:  match hex:    case True{}:      Some{(c - 55 : U32)}    case False{}:      None{}def unhex.h(+c: U32, lo: Bool) -> Maybe<&2, U32>:  match lo:    case True{}:      Some{(c - 87 : U32)}    case False{}:      unhex.H(c, Bool.and(U32.is_le(65, c), U32.is_le(c, 70)))def unhex.d(+c: U32, dec: Bool, lo: Bool) -> Maybe<&2, U32>:  match dec:    case True{}:      Some{(c - 48 : U32)}    case False{}:      unhex.h(c, lo)def unhex(+c: U32) -> Maybe<&2, U32>:  unhex.d(c, Bool.and(U32.is_le(48, c), U32.is_le(c, 57)), Bool.and(U32.is_le(97, c), U32.is_le(c, 102)))def pct.cons(byte: U32, rest: Maybe<&2, String>) -> Maybe<&2, String>:  match rest:    case None{}:      None{}    case Some{s}:      Some{SCon{Chr{byte}, s}}def pct.join2(x: U32, b: Maybe<&2, U32>, rest: Maybe<&2, String>) -> Maybe<&2, String>:  match b:    case None{}:      None{}    case Some{y}:      pct.cons((x * 16 + y : U32), rest)def pct.join(a: Maybe<&2, U32>, b: Maybe<&2, U32>, rest: Maybe<&2, String>) -> Maybe<&2, String>:  match a:    case None{}:      None{}    case Some{x}:      pct.join2(x, b, rest)def pct.decode.last(+c: U32, pct: Bool) -> Maybe<&2, String>:  match pct:    case True{}:      None{}    case False{}:      Some{SCon{Chr{c}, SNil{}}}@unsafedef pct.decode.go(s: String) -> Maybe<&2, String>:  match s:    case SNil{}:      Some{SNil{}}    case SCon{Chr{+c}, t}:      match t:        case SNil{}:          pct.decode.last(c, U32.is_eq(c, 37))        case SCon{Chr{+a}, u}:          match u:            case SNil{}:              Bool.pick(Maybe<&2, String>, U32.is_eq(c, 37), None{}, pct.cons(c, pct.decode.go(SCon{Chr{a}, SNil{}})))            case SCon{Chr{+b}, +r}:              Bool.pick(Maybe<&2, String>, U32.is_eq(c, 37), pct.join(unhex(a), unhex(b), pct.decode.go(r)), pct.cons(c, pct.decode.go(SCon{Chr{a}, SCon{Chr{b}, r}})))def pct.decode(s: String) -> Maybe<&2, String>:  pct.decode.go(s)def take_q.go(s: String, +acc: String) -> String & String:  match s:    case SNil{}:      (String.reverse(acc), SNil{})    case SCon{Chr{+c}, +t}:      Bool.pick(String & String, U32.is_eq(c, 63), (String.reverse(acc), t), take_q.go(t, SCon{Chr{c}, acc}))def take_eq.go(s: String, +acc: String) -> String & String:  match s:    case SNil{}:      (String.reverse(acc), SNil{})    case SCon{Chr{+c}, +t}:      Bool.pick(String & String, U32.is_eq(c, 61), (String.reverse(acc), t), take_eq.go(t, SCon{Chr{c}, acc}))def pair(kv: String) -> String & String:  take_eq.go(kv, SNil{})def qput.decv(m: Map<&2, String>, key: String, v: Maybe<&2, String>) -> Map<&2, String>:  match v:    case None{}:      m    case Some{val}:      Map.set(&2, String, m, key, val)def qput.dec(m: Map<&2, String>, k: Maybe<&2, String>, v: Maybe<&2, String>) -> Map<&2, String>:  match k:    case None{}:      m    case Some{key}:      qput.decv(m, key, v)def qput.kv(m: Map<&2, String>, kv: String & String) -> Map<&2, String>:  (k, v) = kv  qput.dec(m, pct.decode(k), pct.decode(v))def qput(m: Map<&2, String>, kv: String) -> Map<&2, String>:  qput.kv(m, pair(kv))def qfold(xs: List<&2, String>, m: Map<&2, String>) -> Map<&2, String>:  match xs:    case Nil{}:      m    case Con{h, t}:      qfold(t, qput(m, h))def parse.q(path: String, rest: String, hasq: Bool) -> Maybe<&2, Url>:  match hasq:    case False{}:      Some{Url{path, Map.new(&2, String)}}    case True{}:      Some{Url{path, qfold(String.split(rest, '&'), Map.new(&2, String))}}def parse.path(path: Maybe<&2, String>, +rest: String) -> Maybe<&2, Url>:  match path:    case None{}:      None{}    case Some{p}:      parse.q(p, rest, Bool.not(String.is_empty(rest)))def parse.split(pr: String & String) -> Maybe<&2, Url>:  (path, +rest) = pr  parse.path(pct.decode(path), rest)def parse.ok(+s: String, ok: Bool) -> Maybe<&2, Url>:  match ok:    case False{}:      None{}    case True{}:      parse.split(take_q.go(s, SNil{}))def parse(+s: String) -> Maybe<&2, Url>:  parse.ok(s, String.starts_with(s, "/"))def enc.pairs.go(xs: List<&2, Sigma<&2, &2, String, _ => String>>, acc: String) -> String:  match xs:    case Nil{}:      acc    case (k, v) <> t:      enc.pairs.go(t, acc ++ ("&" ++ pct.encode_q(k) ++ "=" ++ pct.encode_q(v)))def enc.pairs(m: Map<&2, String>) -> String:  enc.pairs.go(Map.to_list(&2, String, m), "")def encode.q(path: String, q: String, empty: Bool) -> String:  match empty:    case True{}:      path    case False{}:      path ++ "?" ++ String.drop(q, 1n)def encode.go(path: String, +q: String) -> String:  encode.q(path, q, String.is_empty(q))def encode(u: Url) -> String:  Url{path, query} = u  encode.go(pct.encode_path(path), enc.pairs(query))