]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Response/StatusCode/Internal.hs
Code reorganisation
[Lucu.git] / Network / HTTP / Lucu / Response / StatusCode / Internal.hs
similarity index 79%
rename from Network/HTTP/Lucu/StatusCode/Internal.hs
rename to Network/HTTP/Lucu/Response/StatusCode/Internal.hs
index 026b1a88b16bfdcb7094b8ae2d0dfe66f6f6508d..7d0da98d263b9c3b87d908fc8e5daab194791559 100644 (file)
@@ -3,20 +3,22 @@
   , FlexibleInstances
   , MultiParamTypeClasses
   , OverlappingInstances
+  , OverloadedStrings
   , TemplateHaskell
-  , TypeFamilies
   , UndecidableInstances
   , UnicodeSyntax
   , ViewPatterns
   #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
-module Network.HTTP.Lucu.StatusCode.Internal
+module Network.HTTP.Lucu.Response.StatusCode.Internal
     ( StatusCode(..)
     , SomeStatusCode
     , statusCodes
     )
     where
 import Control.Applicative
+import Control.Applicative.Unicode
+import Control.Monad.Unicode
 import Data.Ascii (Ascii, AsciiBuilder)
 import qualified Data.Ascii as A
 import Data.Attoparsec.Char8
@@ -26,9 +28,11 @@ import Data.Convertible.Base
 import Data.Convertible.Instances.Ascii ()
 import Data.Convertible.Utils
 import Data.List
+import Data.Monoid
 import Language.Haskell.TH.Lib
 import Language.Haskell.TH.Syntax
 import Language.Haskell.TH.Quote
+import Network.HTTP.Lucu.OrphanInstances ()
 import Network.HTTP.Lucu.Parser
 import Prelude.Unicode
 
@@ -46,6 +50,7 @@ class (Eq sc, Show sc) ⇒ StatusCode sc where
     textualStatus ∷ sc → AsciiBuilder
     -- |Wrap the status code into 'SomeStatusCode'.
     fromStatusCode ∷ sc → SomeStatusCode
+    {-# INLINE CONLIKE fromStatusCode #-}
     fromStatusCode = SomeStatusCode
 
 instance StatusCode sc ⇒ ConvertSuccess sc SomeStatusCode where
@@ -74,7 +79,7 @@ instance StatusCode sc ⇒ ConvertAttempt sc AsciiBuilder where
 
 -- |Container type for the 'StatusCode' type class.
 data SomeStatusCode
-    = ∀sc. StatusCode sc ⇒ SomeStatusCode sc
+    = ∀sc. StatusCode sc ⇒ SomeStatusCode !sc
 
 -- |Equivalence of 'StatusCode's. Two 'StatusCode's @α@ and
 -- @β@ are said to be equivalent iff @'numericCode' α '=='
@@ -87,8 +92,11 @@ instance Show SomeStatusCode where
     show (SomeStatusCode sc) = show sc
 
 instance StatusCode SomeStatusCode where
-    numericCode   (SomeStatusCode sc) = numericCode   sc
+    {-# INLINE numericCode #-}
+    numericCode (SomeStatusCode sc) = numericCode sc
+    {-# INLINE textualStatus #-}
     textualStatus (SomeStatusCode sc) = textualStatus sc
+    {-# INLINE CONLIKE fromStatusCode #-}
     fromStatusCode = id
 
 -- |'QuasiQuoter' for 'StatusCode' declarations.
@@ -107,17 +115,17 @@ instance StatusCode SomeStatusCode where
 --
 -- @
 --   data OK = OK deriving ('Eq', 'Show')
---   instance OK where
+--   instance 'StatusCode' OK where
 --     'numericCode'   _ = 200
 --     'textualStatus' _ = 'cs' (\"200 OK\" ∷ Ascii)
 --
 --   data BadRequest = BadRequest deriving ('Eq', 'Show')
---   instance BadRequest where
+--   instance 'StatusCode' BadRequest where
 --     'numericCode'   _ = 400
 --     'textualStatus' _ = 'cs' (\"400 Bad Request\" ∷ Ascii)
 --
 --   data MethodNotAllowed = MethodNotAllowed deriving ('Eq', 'Show')
---   instance MethodNotAllowed where
+--   instance 'StatusCode' MethodNotAllowed where
 --     'numericCode'   _ = 405
 --     'textualStatus' _ = 'cs' (\"405 Method Not Allowed\" ∷ Ascii)
 -- @
@@ -126,22 +134,25 @@ statusCodes = QuasiQuoter {
                 quoteExp  = const unsupported
               , quotePat  = const unsupported
               , quoteType = const unsupported
-              , quoteDec  = (concat <$>) ∘ mapM statusDecl ∘ parseStatusCodes ∘ Lazy.pack
+              , quoteDec  = (concat <$>)
+                            ∘ (mapM statusDecl =≪)
+                            ∘ parseStatusCodes
+                            ∘ Lazy.pack
               }
     where
       unsupported ∷ Monad m ⇒ m α
       unsupported = fail "Unsupported usage of statusCodes quasi-quoter."
 
-parseStatusCodes ∷ Lazy.ByteString → [(Int, [Ascii])]
+parseStatusCodes ∷ Monad m ⇒ Lazy.ByteString → m [(Int, [Ascii])]
 parseStatusCodes src
     = case LP.parse pairs src of
         LP.Fail _ eCtx e
-            → error $ "Unparsable status codes: "
-                    ⧺ intercalate ", " eCtx
-                    ⧺ ": "
-                    ⧺ e
+            → fail $ "Unparsable status codes: "
+                   ⧺ intercalate ", " eCtx
+                   ⧺ ": "
+                   ⧺ e
         LP.Done _ xs
-            → xs
+            → return xs
     where
       pairs ∷ Parser [(Int, [Ascii])]
       pairs = do skipMany endOfLine
@@ -165,35 +176,29 @@ parseStatusCodes src
       word = A.unsafeFromByteString <$> takeWhile1 isAlpha_ascii
 
 statusDecl ∷ (Int, [Ascii]) → Q [Dec]
-statusDecl (num, phrase)
-    = do a  ← dataDecl
-         bs ← instanceDecl
-         return (a:bs)
+statusDecl (num, phrase) = (:) <$> dataDecl ⊛ instanceDecl
     where
+      dataDecl ∷ Q Dec
+      dataDecl = dataD (cxt []) name [] [con] [''Eq, ''Show]
+
       name ∷ Name
       name = mkName $ concatMap cs phrase
 
-      dataDecl ∷ Q Dec
-      dataDecl = dataD (cxt []) name [] [con] [''Eq, ''Show]
+      con ∷ Q Con
+      con = normalC name []
 
       instanceDecl ∷ Q [Dec]
       instanceDecl
           = [d| instance StatusCode $typ where
                   {-# INLINE CONLIKE numericCode #-}
                   numericCode _ = $(lift num)
-                  {-# INLINE CONLIKE textualStatus #-}
-                  textualStatus _ = $txt
+                  {-# INLINE textualStatus #-}
+                  textualStatus _ = cs $(lift txt)
               |]
 
       typ ∷ Q Type
       typ = conT name
 
-      con ∷ Q Con
-      con = return $ NormalC name []
-
-      txt ∷ Q Exp
-      txt = [| cs ($(lift txt') ∷ Ascii) |]
-
-      txt' ∷ String
-      txt' = concat $ intersperse "\x20"
-                    $ show num : map cs phrase
+      txt ∷ Ascii
+      txt = mconcat $ intersperse "\x20"
+                    $ A.unsafeFromString (show num) : phrase