@@ -8,6 +8,7 @@
8{-# LANGUAGE OverloadedStrings #-}
8{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE PolyKinds #-}
9{-# LANGUAGE PolyKinds #-}
10{-# LANGUAGE ScopedTypeVariables #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE TupleSections #-}
11{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE UndecidableInstances #-}
14{-# LANGUAGE UndecidableInstances #-}
@@ -81,6 +82,7 @@ import qualified Data.ByteString as BS
81import Data.ByteString.Lazy (ByteString, fromStrict,
82import Data.ByteString.Lazy (ByteString, fromStrict,
83import qualified Data.ByteString.Lazy.Char8 as BC
84import qualified Data.ByteString.Lazy.Char8 as BC
85+import qualified Data.List.NonEmpty as NE
84import Data.Maybe (isJust)
86import Data.Maybe (isJust)
85import Data.String.Conversions (cs)
87import Data.String.Conversions (cs)
86import qualified Data.Text as TextS
88import qualified Data.Text as TextS
@@ -119,6 +121,12 @@ data OctetStream deriving Typeable
120class Accept ctype where
122class Accept ctype where
121 contentType :: Proxy ctype -> M.MediaType
123 contentType :: Proxy ctype -> M.MediaType
124+ contentType = NE.head . contentTypes
126+ contentTypes :: Proxy ctype -> NE.NonEmpty M.MediaType
127+ contentTypes = (NE.:| []) . contentType
129+ {-# MINIMAL contentType | contentTypes #-}
123-- | @application/json@
131-- | @application/json@
124instance Accept JSON where
132instance Accept JSON where
@@ -219,9 +227,10 @@ instance AllMime '[] where
219 allMime _ = []
227 allMime _ = []
221instance (Accept ctyp, AllMime ctyps) => AllMime (ctyp ': ctyps) where
229instance (Accept ctyp, AllMime ctyps) => AllMime (ctyp ': ctyps) where
222− allMime _ = (contentType pctyp):allMime pctyps
230+ allMime _ = NE.toList (contentTypes pctyp) ++ allMime pctyps
223− where pctyp = Proxy :: Proxy ctyp
232+ pctyp = Proxy :: Proxy ctyp
224− pctyps = Proxy :: Proxy ctyps
233+ pctyps = Proxy :: Proxy ctyps
226canHandleAcceptH :: AllMime list => Proxy list -> AcceptHeader -> Bool
235canHandleAcceptH :: AllMime list => Proxy list -> AcceptHeader -> Bool
227canHandleAcceptH p (AcceptHeader h ) = isJust $ M.matchAccept (allMime p) h
236canHandleAcceptH p (AcceptHeader h ) = isJust $ M.matchAccept (allMime p) h
@@ -235,25 +244,31 @@ class (AllMime list) => AllMimeRender (list :: [*]) a where
235 -> [(M.MediaType, ByteString)] -- content-types/response pairs
244 -> [(M.MediaType, ByteString)] -- content-types/response pairs
237instance OVERLAPPABLE_ ( MimeRender ctyp a ) => AllMimeRender '[ctyp] a where
246instance OVERLAPPABLE_ ( MimeRender ctyp a ) => AllMimeRender '[ctyp] a where
238− allMimeRender _ a = [(contentType pctyp, mimeRender pctyp a)]
247+ allMimeRender _ a = map (, bs) $ NE.toList $ contentTypes pctyp
249+ bs = mimeRender pctyp a
239− where pctyp = Proxy :: Proxy ctyp
250+ pctyp = Proxy :: Proxy ctyp
241instance OVERLAPPABLE_
252instance OVERLAPPABLE_
242 ( MimeRender ctyp a
253 ( MimeRender ctyp a
243 , AllMimeRender (ctyp' ': ctyps) a
254 , AllMimeRender (ctyp' ': ctyps) a
244 ) => AllMimeRender (ctyp ': ctyp' ': ctyps) a where
255 ) => AllMimeRender (ctyp ': ctyp' ': ctyps) a where
257+ (map (, bs) $ NE.toList $ contentTypes pctyp)
258+ ++ allMimeRender pctyps a
245− allMimeRender _ a = (contentType pctyp, mimeRender pctyp a)
260+ bs = mimeRender pctyp a
246− :(allMimeRender pctyps a)
247− where pctyp = Proxy :: Proxy ctyp
261+ pctyp = Proxy :: Proxy ctyp
248− pctyps = Proxy :: Proxy (ctyp' ': ctyps)
262+ pctyps = Proxy :: Proxy (ctyp' ': ctyps)
251-- Ideally we would like to declare a 'MimeRender a NoContent' instance, and
265-- Ideally we would like to declare a 'MimeRender a NoContent' instance, and
252-- then this would be taken care of. However there is no more specific instance
266-- then this would be taken care of. However there is no more specific instance
253-- between that and 'MimeRender JSON a', so we do this instead
267-- between that and 'MimeRender JSON a', so we do this instead
254instance OVERLAPPING_ ( Accept ctyp ) => AllMimeRender '[ctyp] NoContent where
268instance OVERLAPPING_ ( Accept ctyp ) => AllMimeRender '[ctyp] NoContent where
255− allMimeRender _ _ = [(contentType pctyp, "")]
269+ allMimeRender _ _ = map (, "") $ NE.toList $ contentTypes pctyp
256− where pctyp = Proxy :: Proxy ctyp
271+ pctyp = Proxy :: Proxy ctyp
258instance OVERLAPPING_
273instance OVERLAPPING_
259 ( AllMime (ctyp ': ctyp' ': ctyps)
274 ( AllMime (ctyp ': ctyp' ': ctyps)
@@ -274,10 +289,13 @@ instance AllMimeUnrender '[] a where
274instance ( MimeUnrender ctyp a
289instance ( MimeUnrender ctyp a
275 , AllMimeUnrender ctyps a
290 , AllMimeUnrender ctyps a
276 ) => AllMimeUnrender (ctyp ': ctyps) a where
291 ) => AllMimeUnrender (ctyp ': ctyps) a where
277− allMimeUnrender _ val = (contentType pctyp, mimeUnrender pctyp val)
292+ allMimeUnrender _ bs =
293+ (map (, x) $ NE.toList $ contentTypes pctyp)
278− :(allMimeUnrender pctyps val)
294+ ++ allMimeUnrender pctyps bs
296+ x = mimeUnrender pctyp bs
279− where pctyp = Proxy :: Proxy ctyp
297+ pctyp = Proxy :: Proxy ctyp
280− pctyps = Proxy :: Proxy ctyps
298+ pctyps = Proxy :: Proxy ctyps
282--------------------------------------------------------------------------
300--------------------------------------------------------------------------
283-- * MimeRender Instances
301-- * MimeRender Instances