]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/StatusCode/Internal.hs
StatusCode: modified again
[Lucu.git] / Network / HTTP / Lucu / StatusCode / Internal.hs
index 24988eefb2707d4e94aede4ade56f8e1a937d177..e3122da1f55e21af4587abf5cf7d4175e8ccdd93 100644 (file)
@@ -1,24 +1,31 @@
 {-# LANGUAGE
     ExistentialQuantification
   , FlexibleInstances
+  , MultiParamTypeClasses
+  , OverlappingInstances
   , TemplateHaskell
+  , UndecidableInstances
   , UnicodeSyntax
   , ViewPatterns
   #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 module Network.HTTP.Lucu.StatusCode.Internal
     ( StatusCode(..)
-    , SomeStatusCode(..)
+    , SomeStatusCode
     , (≈)
     , (≉)
     , statusCodes
     )
     where
 import Control.Applicative
-import Data.Ascii (Ascii)
+import Data.Ascii (Ascii, AsciiBuilder)
 import qualified Data.Ascii as A
-import Data.Attoparsec.Char8 as P
-import Data.Attoparsec.Lazy as LP
+import Data.Attoparsec.Char8
+import qualified Data.Attoparsec.Lazy as LP
 import qualified Data.ByteString.Lazy.Char8 as Lazy
+import Data.Convertible.Base
+import Data.Convertible.Instances.Ascii ()
+import Data.Convertible.Utils
 import Data.List
 import Language.Haskell.TH.Lib
 import Language.Haskell.TH.Syntax
@@ -26,10 +33,10 @@ import Language.Haskell.TH.Quote
 import Network.HTTP.Lucu.Parser
 import Prelude.Unicode
 
--- |The type class for HTTP status codes.
+-- |Type class for HTTP status codes.
 --
 -- Declaring types for each statuses is surely a pain. See:
--- 'statusCodes'
+-- 'statusCodes' quasi-quoter.
 --
 -- Minimal complete definition: 'numericCode' and 'textualStatus'.
 class Show sc ⇒ StatusCode sc where
@@ -37,24 +44,24 @@ class Show sc ⇒ StatusCode sc where
     numericCode ∷ sc → Int
     -- |Return the combination of 3-digit integer and reason phrase
     -- for this status e.g. @200 OK@
-    textualStatus ∷ sc → Ascii
+    textualStatus ∷ sc → AsciiBuilder
     -- |Wrap the status code into 'SomeStatusCode'.
     fromStatusCode ∷ sc → SomeStatusCode
     fromStatusCode = SomeStatusCode
 
--- |Container type for 'StatusCode' type class.
+instance StatusCode sc ⇒ Eq sc where
+    (==) = (≈)
+
+-- |Container type for the 'StatusCode' type class.
 data SomeStatusCode
     = ∀sc. StatusCode sc ⇒ SomeStatusCode sc
 
 instance Show SomeStatusCode where
     show (SomeStatusCode sc) = show sc
 
-instance Eq SomeStatusCode where
-    (SomeStatusCode α) == (SomeStatusCode β) = α ≈ β
-
 infix 4 ≈, ≉
--- |Two 'StatusCode's @a@ and @b@ are said to be equivalent iff
--- @'numericCode' a '==' 'numericCode' b@.
+-- |Equivalence of 'StatusCode's. Two 'StatusCode's @a@ and @b@ are
+-- said to be equivalent iff @'numericCode' a '==' 'numericCode' b@.
 --
 -- U+2248, ALMOST EQUAL TO
 (≈) ∷ (StatusCode α, StatusCode β) ⇒ α → β → Bool
@@ -73,6 +80,22 @@ instance StatusCode SomeStatusCode where
     textualStatus (SomeStatusCode sc) = textualStatus sc
     fromStatusCode = id
 
+instance StatusCode sc ⇒ ConvertSuccess sc Ascii where
+    {-# INLINE convertSuccess #-}
+    convertSuccess = convertSuccessVia ((⊥) ∷ AsciiBuilder)
+
+instance StatusCode sc ⇒ ConvertSuccess sc AsciiBuilder where
+    {-# INLINE convertSuccess #-}
+    convertSuccess = textualStatus
+
+instance StatusCode sc ⇒ ConvertAttempt sc Ascii where
+    {-# INLINE convertAttempt #-}
+    convertAttempt = return ∘ cs
+
+instance StatusCode sc ⇒ ConvertAttempt sc AsciiBuilder where
+    {-# INLINE convertAttempt #-}
+    convertAttempt = return ∘ cs
+
 -- |'QuasiQuoter' for 'StatusCode' declarations.
 --
 -- Top-level splicing
@@ -91,17 +114,17 @@ instance StatusCode SomeStatusCode where
 --   data OK = OK deriving ('Show')
 --   instance OK where
 --     'numericCode'   _ = 200
---     'textualStatus' _ = 'A.unsafeFromString' \"200 OK\"
+--     'textualStatus' _ = 'cs' (\"200 OK\" ∷ Ascii)
 --
 --   data BadRequest = BadRequest deriving ('Show')
 --   instance BadRequest where
 --     'numericCode'   _ = 400
---     'textualStatus' _ = 'A.unsafeFromString' \"400 Bad Request\"
+--     'textualStatus' _ = 'cs' (\"400 Bad Request\" ∷ Ascii)
 --
 --   data MethodNotAllowed = MethodNotAllowed deriving ('Show')
 --   instance MethodNotAllowed where
 --     'numericCode'   _ = 405
---     'textualStatus' _ = 'A.unsafeFromString' \"405 Method Not Allowed\"
+--     'textualStatus' _ = 'cs' (\"405 Method Not Allowed\" ∷ Ascii)
 -- @
 statusCodes ∷ QuasiQuoter
 statusCodes = QuasiQuoter {
@@ -144,7 +167,7 @@ parseStatusCodes src
              "pair"
 
       word ∷ Parser Ascii
-      word = A.unsafeFromByteString <$> P.takeWhile1 isAlpha_ascii
+      word = A.unsafeFromByteString <$> takeWhile1 isAlpha_ascii
 
 statusDecl ∷ (Int, [Ascii]) → Q [Dec]
 statusDecl (num, phrase)
@@ -153,7 +176,7 @@ statusDecl (num, phrase)
          return (a:bs)
     where
       name ∷ Name
-      name = mkName $ concatMap A.toString phrase
+      name = mkName $ concatMap cs phrase
 
       dataDecl ∷ Q Dec
       dataDecl = dataD (cxt []) name [] [con] [''Show]
@@ -161,9 +184,9 @@ statusDecl (num, phrase)
       instanceDecl ∷ Q [Dec]
       instanceDecl
           = [d| instance StatusCode $typ where
-                  {-# INLINE numericCode #-}
+                  {-# INLINE CONLIKE numericCode #-}
                   numericCode _ = $(lift num)
-                  {-# INLINE textualStatus #-}
+                  {-# INLINE CONLIKE textualStatus #-}
                   textualStatus _ = $txt
               |]
 
@@ -174,8 +197,8 @@ statusDecl (num, phrase)
       con = return $ NormalC name []
 
       txt ∷ Q Exp
-      txt = [| A.unsafeFromString $(lift txt') |]
+      txt = [| cs ($(lift txt') ∷ Ascii) |]
 
       txt' ∷ String
       txt' = concat $ intersperse "\x20"
-                    $ show num : map A.toString phrase
+                    $ show num : map cs phrase