blob: 5bfe26c2ed2e44275aff6b04598de525676ea95d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
(.require
[library
[lux (.except)
[abstract
[monad (.only do)]
[codec (.only Codec)]
[equivalence (.only Equivalence)]]
[control
["?" parser]
["[0]" try (.only Try)]]
[data
["[0]" text (.only)
["%" \\format]
["?[1]" \\parser (.only Parser)]]
[collection
["[0]" list (.use "[1]#[0]" functor)]
["[0]" dictionary (.only Dictionary)]]]
[math
[number
["[0]" nat]]]
[world
[net
["[0]" uri
["[1]" encoding]]]]]])
(type .public Query
(Dictionary Text Text))
(def .public empty
Query
(dictionary.empty text.hash))
(def .public equivalence
(Equivalence Query)
(dictionary.equivalence text.equivalence))
(def component
(Parser Text)
(?.rec
(function (_ component)
(do [! ?.monad]
[head (?text.some (?text.none_of "+%&;"))]
(all ?.either
(?.after (?.either ?text.end
(?text.this "&"))
(in head))
(do !
[_ (?text.this "+")
tail component]
(in (%.format head " " tail)))
(do !
[_ (?text.this "%")
code (|> (?text.exactly 2 ?text.hexadecimal)
(?.codec nat.hex)
(of ! each text.of_char))
tail component]
(in (%.format head code tail))))))))
(def separators
"&;")
(def assignment
"=")
(def invalid
(%.format "=" "&;"))
(def (form query)
(-> Query (Parser Query))
(all ?.either
(do ?.monad
[_ ?text.end]
(in query))
(do [! ?.monad]
[key (?text.some (?text.none_of ..invalid))
key (?text.local key ..component)
key (?.of_try (uri.decoded key))]
(?.either (do !
[_ (?text.this ..assignment)
value ..component
value (?.of_try (uri.decoded value))]
(form (dictionary.has key value query)))
(do !
[_ (all ?.or
(?text.one_of ..separators)
?text.end)]
(form (dictionary.has key "" query)))))
... if invalid form data, just stop parsing...
(of ?.monad in query)))
(def format
(%.Format Query)
(|>> dictionary.entries
(list#each (function (_ [key value])
(%.format (uri.encoded key) "=" (uri.encoded value))))
(text.interposed "&")))
(def query
(-> Text (Try Query))
(?text.result (..form ..empty)))
(def .public codec
(Codec Text Query)
(implementation
(def encoded ..format)
(def decoded ..query)))
|