0 | module HTTP.API.Decode
2 | import Data.List.Quantifiers as L
3 | import Derive.Prelude
5 | import HTTP.Header.Types
6 | import HTTP.RequestErr
10 | import JSON.Simple.Derive
13 | %language ElabReflection
18 | data DecodeErr : Type where
25 | ReadErr : (type, value : String) -> (details : String) -> DecodeErr
31 | ContentErr : (type : String) -> (details : String) -> DecodeErr
34 | Msg : (message : String) -> DecodeErr
36 | %runElab derive "DecodeErr" [Show,Eq,FromJSON,ToJSON]
40 | readErr : (type : String) -> (value : ByteString) -> DecodeErr
41 | readErr type value = ReadErr type (toString value) ""
45 | contentErr : (type : String) -> Interpolation a => a -> DecodeErr
46 | contentErr type = ContentErr type . interpolate
50 | setType : String -> DecodeErr -> DecodeErr
51 | setType t (ReadErr _ v d) = ReadErr t v d
52 | setType t (ContentErr _ d) = ContentErr t d
53 | setType t (Msg m) = Msg m
57 | setValue : String -> DecodeErr -> DecodeErr
58 | setValue v (ReadErr t _ d) = ReadErr t v d
59 | setValue _ err = err
63 | modMsg : (String -> String) -> DecodeErr -> DecodeErr
64 | modMsg f (ReadErr t v d) = ReadErr t v (f d)
65 | modMsg f (ContentErr t d) = ContentErr t (f d)
66 | modMsg f (Msg m) = Msg (f m)
74 | interface Decode (0 a : Type) where
75 | decode : ByteString -> Either DecodeErr a
79 | public export %inline
80 | decodeAs : (0 a : Type) -> Decode a => ByteString -> Either DecodeErr a
86 | interface DecodeMany (0 a : Type) where
87 | simulateDecode : List ByteString -> Maybe (List ByteString)
89 | decodeMany : List ByteString -> Either DecodeErr (List ByteString, a)
92 | Decode a => DecodeMany a where
93 | simulateDecode [] = Nothing
94 | simulateDecode (b::bs) = Just bs
96 | decodeMany [] = Left (Msg "Unexpected end of URL path")
97 | decodeMany (b::bs) = (bs,) <$> decode b
104 | -> Either DecodeErr (List ByteString,SnocList a)
105 | decodeAll sx d [] = Right ([],sx)
106 | decodeAll sx d (x :: xs) =
107 | case decode @{d} x of
108 | Right v => decodeAll (sx:<v) d xs
109 | Left err => Left err
112 | Decode a => DecodeMany (SnocList a) where
113 | simulateDecode bs = Just []
114 | decodeMany = decodeAll [<] %search
117 | Decode a => DecodeMany (List a) where
118 | simulateDecode bs = Just []
119 | decodeMany bs = map (<>> []) <$> decodeAll [<] %search bs
122 | L.All.All (DecodeMany . f) ts
124 | -> Maybe (List ByteString)
125 | simulateHL [] xs = Just xs
126 | simulateHL (x :: y) xs =
127 | case simulateDecode @{x} xs of
129 | Just xs2 => simulateHL y xs2
132 | L.All.All (DecodeMany . f) ts
134 | -> Either DecodeErr (List ByteString, L.All.All f ts)
135 | decodeHL [] xs = Right (xs, [])
136 | decodeHL (x :: y) xs =
137 | case decodeMany @{x} xs of
138 | Left err => Left err
139 | Right (xs2, v) => map (v::) <$> decodeHL y xs2
142 | (all : L.All.All (DecodeMany . f) ts) => DecodeMany (L.All.All f ts) where
143 | simulateDecode = simulateHL all
144 | decodeMany = decodeHL all
150 | -> Maybe (List ByteString)
151 | simulateN x 0 xs = Just xs
152 | simulateN x (S n) xs =
153 | case simulateDecode @{x} xs of
155 | Just xs2 => simulateN x n xs2
161 | -> Either DecodeErr (List ByteString, Vect n t)
162 | decodeN x 0 xs = Right (xs, [])
163 | decodeN x (S n) xs =
164 | case decodeMany @{x} xs of
165 | Left err => Left err
166 | Right (xs2, v) => map (v::) <$> decodeN x n xs2
169 | {n : Nat} -> (x : DecodeMany a) => DecodeMany (Vect n a) where
170 | simulateDecode = simulateN x n
171 | decodeMany = decodeN x n
177 | namespace DecodeVia
179 | interface DecodeVia (0 from, to : Type) where
180 | fromBytes : Parameters -> ByteString -> Either DecodeErr from
181 | decodeFrom : from -> Either DecodeErr to
182 | mediaType : MediaType
186 | {auto d : DecodeVia from to}
189 | -> Either DecodeErr to
190 | decodeVia ps bs = fromBytes @{d} ps bs >>= decodeFrom
193 | interface FromFormData a where
194 | fromFormData : FormData -> Either DecodeErr a
201 | Decode ByteString where decode = Right
204 | Decode String where decode = Right . toString
208 | {auto r : Decode a}
210 | -> (a -> Either String b)
212 | -> Either DecodeErr b
213 | refinedEither t f bs = Prelude.do
214 | v <- mapFst (setType t) $
decodeAs a bs
215 | mapFst (ReadErr t (toString bs)) (f v)
219 | {auto r : Decode a}
221 | -> (details : Lazy String)
224 | -> Either DecodeErr b
225 | refined t details f bs = Prelude.do
226 | v <- mapFst (setType t) $
decodeAs a bs
228 | Nothing => Left $
ReadErr t (toString bs) details