src/pct.bend
emerging-ezhttp@0.21.0.0 · 89 lines · 13 definitions
1
2
3
4
5
6import Base
7
8
9def unreserved(+cp: U32) -> Bool:
10 Bool.or(Bool.and(U32.is_le(65, cp), U32.is_le(cp, 90)),
11 Bool.or(Bool.and(U32.is_le(97, cp), U32.is_le(cp, 122)),
12 Bool.or(Bool.and(U32.is_le(48, cp), U32.is_le(cp, 57)),
13 Bool.or(U32.is_eq(cp, 45),
14 Bool.or(U32.is_eq(cp, 46),
15 Bool.or(U32.is_eq(cp, 95), U32.is_eq(cp, 126)))))))
16
17
18
19def safe(slash: Bool, +cp: U32) -> Bool:
20 Bool.or(unreserved(cp), Bool.and(U32.is_eq(cp, 47), slash))
21
22
23def hex(+nib: U32) -> Char:
24 Chr{Bool.pick(U32, U32.is_lt(nib, 10), U32.add(48, nib), U32.add(55, nib))}
25
26
27def pct(bytes: List<&2, U32>, rest: String) -> String:
28 match bytes:
29 case []:
30 rest
31 case +byte <> tail:
32 SCon{'%', SCon{hex(U32.shrn(byte, 4n)), SCon{hex(U32.and(byte, 15)),
33 pct(tail, rest)}}}
34
35
36def cont(+cp: U32, shift: Nat) -> U32:
37 U32.or(128, U32.and(U32.shrn(cp, shift), 63))
38
39
40def utf8.four(+cp: U32) -> List<&2, U32>:
41 [U32.or(240, U32.shrn(cp, 18n)), cont(cp, 12n), cont(cp, 6n), cont(cp, 0n)]
42
43
44def utf8.three(+cp: U32, fits: Bool) -> List<&2, U32>:
45 match fits:
46 case True{}:
47 [U32.or(224, U32.shrn(cp, 12n)), cont(cp, 6n), cont(cp, 0n)]
48 case False{}:
49 utf8.four(cp)
50
51
52def utf8.two(+cp: U32, fits: Bool) -> List<&2, U32>:
53 match fits:
54 case True{}:
55 [U32.or(192, U32.shrn(cp, 6n)), cont(cp, 0n)]
56 case False{}:
57 utf8.three(cp, U32.is_lt(cp, 65536))
58
59
60def utf8.one(+cp: U32, fits: Bool) -> List<&2, U32>:
61 match fits:
62 case True{}:
63 [cp]
64 case False{}:
65 utf8.two(cp, U32.is_lt(cp, 2048))
66
67
68def utf8(+cp: U32) -> List<&2, U32>:
69 utf8.one(cp, U32.is_lt(cp, 128))
70
71
72def one.of(+cp: U32, rest: String, kept: Bool) -> String:
73 match kept:
74 case True{}:
75 SCon{Chr{cp}, rest}
76 case False{}:
77 pct(utf8(cp), rest)
78
79
80def one(slash: Bool, +cp: U32, rest: String) -> String:
81 one.of(cp, rest, safe(slash, cp))
82
83
84def quote(+slash: Bool, shift: String) -> String:
85 match shift:
86 case SNil{}:
87 SNil{}
88 case SCon{Chr{+cp}, tail}:
89 one(slash, cp, quote(slash, tail))