File: JSON.hs

package info (click to toggle)
haskell-http2 5.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,180 kB
  • sloc: haskell: 8,657; makefile: 5
file content (117 lines) | stat: -rw-r--r-- 2,974 bytes parent folder | download
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
107
108
109
110
111
112
113
114
115
116
117
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module JSON (
    Test (..),
    Case (..),
    HeaderList,
) where

#if __GLASGOW_HASKELL__ < 709
import Control.Applicative
#endif
import Control.Monad (mzero)
import Data.Aeson
import qualified Data.Aeson.Key as Key
import qualified Data.Aeson.KeyMap as H
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as B8
import Data.Text (Text)
import qualified Data.Text as T
import Data.Vector ((!))
import qualified Data.Vector as V
import Network.HPACK

{-
import Data.Aeson.Encode.Pretty (encodePretty)
import qualified Data.ByteString.Lazy as BL

main :: IO ()
main = do
    bs <- BL.getContents
    let Right x = eitherDecode bs :: Either String Test
    BL.putStr $ encodePretty x
-}

data Test = Test
    { description :: String
    , cases :: [Case]
    }
    deriving (Show)

data Case = Case
    { size :: Maybe Int
    , wire :: ByteString
    , headers :: HeaderList
    , seqno :: Maybe Int
    }
    deriving (Show)

instance FromJSON Test where
    parseJSON (Object o) =
        Test
            <$> o .: "description"
            <*> o .: "cases"
    parseJSON _ = mzero

instance ToJSON Test where
    toJSON (Test desc cs) =
        object
            [ "description" .= desc
            , "cases" .= cs
            ]

instance FromJSON Case where
    parseJSON (Object o) =
        Case
            <$> o .:? "header_table_size"
            <*> (textToByteString <$> (o .: "wire"))
            <*> o .: "headers"
            <*> o .:? "seqno"
    parseJSON _ = mzero

instance ToJSON Case where
    toJSON (Case (Just siz) w hs no) =
        object
            [ "header_table_size" .= siz
            , "wire" .= byteStringToText w
            , "headers" .= hs
            , "seqno" .= no
            ]
    toJSON (Case Nothing w hs no) =
        object
            [ "wire" .= byteStringToText w
            , "headers" .= hs
            , "seqno" .= no
            ]

instance {-# OVERLAPPING #-} FromJSON HeaderList where
    parseJSON (Array a) = mapM parseJSON $ V.toList a
    parseJSON _ = mzero

instance {-# OVERLAPPING #-} ToJSON HeaderList where
    toJSON hs = toJSON $ map toJSON hs

instance {-# OVERLAPPING #-} FromJSON Header where
    parseJSON (Array a) = pure (toKey (a ! 0), toValue (a ! 1)) -- old
      where
        toKey = toValue
    parseJSON (Object o) = pure (textToByteString (Key.toText k), toValue v) -- new
      where
        (k, v) = head $ H.toList o
    parseJSON _ = mzero

instance {-# OVERLAPPING #-} ToJSON Header where
    toJSON (k, v) = object [Key.fromText (byteStringToText k) .= byteStringToText v]

textToByteString :: Text -> ByteString
textToByteString = B8.pack . T.unpack

byteStringToText :: ByteString -> Text
byteStringToText = T.pack . B8.unpack

toValue :: Value -> ByteString
toValue (String s) = textToByteString s
toValue _ = error "toValue"