/
Body.purs
52 lines (40 loc) · 1.49 KB
/
Body.purs
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
module Epicbot.Web.Body
( asHashMap
) where
import Prelude
import Control.Alt ((<|>))
import Data.Either (hush)
import Data.Foldable (class Foldable)
import Data.Foldable as Foldable
import Data.HashMap (HashMap)
import Data.HashMap as HashMap
import Data.List (List(..))
import Data.List as List
import Data.Maybe (Maybe(..), fromMaybe)
import Data.String.CodeUnits as CodeUnits
import Data.Tuple (Tuple(..))
import Text.Parsing.StringParser (Parser, runParser, try)
import Text.Parsing.StringParser.CodePoints (anyChar, oneOf, eof, string)
import Text.Parsing.StringParser.Combinators (lookAhead, manyTill, sepBy)
asString :: forall f. Foldable f => f Char -> String
asString = Foldable.foldMap CodeUnits.singleton
endOfEntry :: Parser Unit
endOfEntry = lookAhead $ (oneOf ['=', '&'] *> pure unit) <|> eof
parseToken :: Parser String
parseToken = asString <$> manyTill anyChar endOfEntry
parseGoodEntry :: Parser (Tuple String String)
parseGoodEntry = do
key <- parseToken <* string "="
val <- parseToken
pure $ Tuple key val
parseBadEntry :: Parser Unit
parseBadEntry = parseToken *> pure unit
parseEntry :: Parser (Maybe (Tuple String String))
parseEntry =
try (Just <$> parseGoodEntry) <|> (parseBadEntry *> pure Nothing)
parseQuery :: Parser (List (Tuple String String))
parseQuery = do
entries <- sepBy parseEntry $ string "&"
pure $ List.catMaybes entries
asHashMap :: String -> HashMap String String
asHashMap = HashMap.fromFoldable <<< fromMaybe Nil <<< hush <<< runParser parseQuery