]> gitweb @ CieloNegro.org - Lucu.git/commitdiff
code cleanup
authorPHO <pho@cielonegro.org>
Tue, 1 Nov 2011 14:40:51 +0000 (23:40 +0900)
committerPHO <pho@cielonegro.org>
Tue, 1 Nov 2011 14:40:51 +0000 (23:40 +0900)
Network/HTTP/Lucu/ETag.hs
Network/HTTP/Lucu/MIMEType.hs
Network/HTTP/Lucu/MIMEType/Guess.hs
Network/HTTP/Lucu/MultipartForm.hs
Network/HTTP/Lucu/Parser.hs
Network/HTTP/Lucu/Resource.hs

index 76df18378bf3e48417dddd8c73dc6222b65d5136..d87100095a71e78cafeba5435cdf02c397111b26 100644 (file)
@@ -20,6 +20,7 @@ import Data.Ascii (Ascii, AsciiBuilder)
 import qualified Data.Ascii as A
 import Data.Attoparsec.Char8
 import Data.Monoid.Unicode
+import Network.HTTP.Lucu.Parser
 import Network.HTTP.Lucu.Parser.Http hiding (token)
 import Network.HTTP.Lucu.Utils
 import Prelude.Unicode
@@ -52,15 +53,9 @@ printETag et
 parseETag ∷ Ascii → ETag
 {-# INLINEABLE parseETag #-}
 parseETag str
-    = case parseOnly p $ A.toByteString str of
+    = case parseOnly (finishOff eTag) $ A.toByteString str of
         Right et → et
         Left err → error ("unparsable ETag: " ⧺ A.toString str ⧺ ": " ⧺ err)
-    where
-      p ∷ Parser ETag
-      {-# INLINE p #-}
-      p = do et ← eTag
-             endOfInput
-             return et
 
 -- |This is equivalent to @'ETag' 'False'@. If you want to generate an
 -- ETag from a file, try using
index ab0e06596320d343164211017a8725ada3b9f07b..1aebc9f56b1233b34a75384d6a45db7441125b7c 100644 (file)
@@ -22,6 +22,7 @@ import Data.Attoparsec.Char8 as P
 import Data.Map (Map)
 import Data.Monoid.Unicode
 import Data.Text (Text)
+import Network.HTTP.Lucu.Parser
 import Network.HTTP.Lucu.Parser.Http
 import Network.HTTP.Lucu.RFC2231
 import Prelude hiding (min)
@@ -59,15 +60,9 @@ printMIMEType (MIMEType maj min params)
 parseMIMEType ∷ Ascii → MIMEType
 {-# INLINEABLE parseMIMEType #-}
 parseMIMEType str
-    = case parseOnly p $ A.toByteString str of
+    = case parseOnly (finishOff mimeType) $ A.toByteString str of
         Right  t → t
         Left err → error ("unparsable MIME Type: " ⧺ A.toString str ⧺ ": " ⧺ err)
-    where
-      p ∷ Parser MIMEType
-      {-# INLINE p #-}
-      p = do t ← mimeType
-             endOfInput
-             return t
 
 -- |'Parser' for an 'MIMEType'.
 mimeType ∷ Parser MIMEType
index d8bca8e785658efa5390862f8baa97c071a93f58..10c11e41c128cc7446082e0f3e5ed810f4a92cf6 100644 (file)
@@ -31,6 +31,7 @@ import Language.Haskell.Exts.Extension
 import Language.Haskell.Exts.Pretty
 import Language.Haskell.Exts.Syntax
 import Network.HTTP.Lucu.MIMEType
+import Network.HTTP.Lucu.Parser
 import Prelude.Unicode
 import System.FilePath
 
@@ -39,16 +40,16 @@ type ExtMap = Map Text MIMEType
 
 -- |Guess the MIME Type of a file.
 guessTypeByFileName ∷ ExtMap → FilePath → Maybe MIMEType
-guessTypeByFileName extMap fpath
+guessTypeByFileName em fpath
     = case takeExtension fpath of
         []      → Nothing
-        (_:ext) → M.lookup (T.pack ext) extMap
+        (_:ext) → M.lookup (T.pack ext) em
 
 -- |Read an Apache mime.types and parse it.
 parseExtMapFile ∷ FilePath → IO ExtMap
 parseExtMapFile fpath
     = do file ← B.readFile fpath
-         case LP.parse extMapP file of
+         case LP.parse (finishOff extMap) file of
            LP.Done _ xs
                → case compile xs of
                     Right m → return m
@@ -60,10 +61,8 @@ parseExtMapFile fpath
            LP.Fail _ _ e
                → fail ("Failed to parse: " ⧺ fpath ⧺ ": " ⧺ e)
 
-extMapP ∷ Parser [ (MIMEType, [Text]) ]
-extMapP = do xs ← P.many (try comment <|> try validLine <|> emptyLine)
-             endOfInput
-             return $ catMaybes xs
+extMap ∷ Parser [ (MIMEType, [Text]) ]
+extMap = catMaybes <$> P.many (try comment <|> try validLine <|> emptyLine)
     where
       isSpc ∷ Char → Bool
       isSpc c = c ≡ '\x20' ∨ c ≡ '\x09'
@@ -116,7 +115,7 @@ compile = go (∅) ∘ concat ∘ map tr
 -- The module "Network.HTTP.Lucu.MIMEType.DefaultExtensionMap" is
 -- surely generated using this function.
 serializeExtMap ∷ ExtMap → String → String → String
-serializeExtMap extMap moduleName variableName
+serializeExtMap em moduleName variableName
     = let hsModule  = Module (⊥) (ModuleName moduleName) modPragma
                       Nothing (Just exports) imports decls
           modPragma = [ LanguagePragma (⊥) [ name (show OverloadedStrings) ] ]
@@ -144,7 +143,7 @@ serializeExtMap extMap moduleName variableName
         comment ⧺ prettyPrint hsModule ⧺ "\n"
     where
       records ∷ [Exp]
-      records = map record $ M.assocs extMap
+      records = map record $ M.assocs em
 
       record ∷ (Text, MIMEType) → Exp
       record (ext, mime)
index a04b4a059f9a28c7e10b3ffc6b7f144b30df0252..16d8f28017425e35fe0273e9c39e7326bea458a1 100644 (file)
@@ -39,6 +39,7 @@ import Data.Text (Text)
 import qualified Data.Text as T
 import Network.HTTP.Lucu.Headers
 import Network.HTTP.Lucu.MIMEType
+import Network.HTTP.Lucu.Parser
 import Network.HTTP.Lucu.Parser.Http
 import Network.HTTP.Lucu.RFC2231
 import Prelude.Unicode
@@ -131,12 +132,7 @@ prologue boundary
       "prologue"
 
 epilogue ∷ Parser ()
-epilogue = ( (string "--" <?> "suffix")
-             *>
-             crlf
-             *>
-             endOfInput
-           )
+epilogue = finishOff ((string "--" <?> "suffix") *> crlf)
            <?>
            "epilogue"
 
@@ -172,16 +168,12 @@ getContDispo hdrs
         Nothing
             → throwError "Content-Disposition is missing"
         Just str
-            → case parseOnly p $ A.toByteString str of
+            → case parseOnly (finishOff contentDisposition) $ A.toByteString str of
                  Right  d → return d
                  Left err → throwError $ "malformed Content-Disposition: "
                                        ⧺ A.toString str
                                        ⧺ ": "
                                        ⧺ err
-    where
-      p = do dispo ← contentDisposition
-             endOfInput
-             return dispo
 
 contentDisposition ∷ Parser ContDispo
 contentDisposition
@@ -196,16 +188,12 @@ getContType hdrs
         Nothing
             → return Nothing
         Just str
-            → case parseOnly p $ A.toByteString str of
+            → case parseOnly (finishOff mimeType) $ A.toByteString str of
                  Right  d → return $ Just d
                  Left err → throwError $ "malformed Content-Type: "
                                        ⧺ A.toString str
                                        ⧺ ": "
                                        ⧺ err
-    where
-      p = do t ← mimeType
-             endOfInput
-             return t
 
 getBody ∷ MonadError String m
         ⇒ Ascii
index ce4371878890301eb152d3b9ef55c526c4127174..b31d4b89be473835df40f9a1dcf72d97d526b5db 100644 (file)
@@ -5,16 +5,26 @@
 -- use this module directly.
 module Network.HTTP.Lucu.Parser
     ( atMost
+    , finishOff
     )
     where
 import Control.Applicative
 import Control.Applicative.Unicode
+import Control.Monad.Unicode
+import Data.Attoparsec
+import Prelude.Unicode
 
 -- |@'atMost' n v@ is like @'P.many' v@ but accumulates @v@ at most
 -- @n@ times.
-atMost ∷ Alternative f ⇒ Int → f a → f [a]
+atMost ∷ Alternative f ⇒ Int → f α → f [α]
 {-# INLINE atMost #-}
 atMost 0 _ = pure []
 atMost n v = ( (:) <$> v ⊛ atMost (n-1) v )
              <|>
              pure []
+
+-- |@'finishOff' p@ is equivalent to @p '>>=' \a -> endOfInput '>>'
+-- 'return' a@.
+finishOff ∷ Parser α → Parser α
+{-# INLINE finishOff #-}
+finishOff = ((endOfInput *>) ∘ return =≪)
index aee29d56f95682c7550623176267f23e6230d23b..474f79adca923a7781d3d40535d047807cc85f33 100644 (file)
@@ -169,6 +169,7 @@ import qualified Network.HTTP.Lucu.Headers as H
 import Network.HTTP.Lucu.HttpVersion
 import Network.HTTP.Lucu.Interaction
 import Network.HTTP.Lucu.MultipartForm
+import Network.HTTP.Lucu.Parser
 import Network.HTTP.Lucu.Request
 import Network.HTTP.Lucu.Resource.Internal
 import Network.HTTP.Lucu.Response
@@ -256,14 +257,10 @@ getAccept
            Nothing
                → return []
            Just accept
-               → case P.parseOnly p (A.toByteString accept) of
+               → case P.parseOnly (finishOff mimeTypeList) (A.toByteString accept) of
                     Right xs → return xs
                     Left  _  → abort $ mkAbortion' BadRequest
                                      $ "Unparsable Accept: " ⊕ A.toText accept
-    where
-      p = do xs ← mimeTypeList
-             P.endOfInput
-             return xs
 
 -- |Return the list of @(contentCoding, qvalue)@ enumerated on the
 -- value of request header \"Accept-Encoding\". The list is sorted in
@@ -288,15 +285,11 @@ getAcceptEncoding
                       -- identity のみが許される。
                       return [("identity", Nothing)]
                  else
-                     case P.parseOnly p (A.toByteString ae) of
+                     case P.parseOnly (finishOff acceptEncodingList) (A.toByteString ae) of
                        Right xs → return $ map toTuple $ reverse $ sort xs
                        Left  _  → abort $ mkAbortion' BadRequest
                                         $ "Unparsable Accept-Encoding: " ⊕ A.toText ae
     where
-      p = do xs ← acceptEncodingList
-             P.endOfInput
-             return xs
-
       toTuple (AcceptEncoding {..})
           = (aeEncoding, aeQValue)
 
@@ -316,14 +309,10 @@ getContentType
            Nothing
                → return Nothing
            Just cType
-               → case P.parseOnly p (A.toByteString cType) of
+               → case P.parseOnly (finishOff mimeType) (A.toByteString cType) of
                     Right t → return $ Just t
                     Left  _ → abort $ mkAbortion' BadRequest
                                     $ "Unparsable Content-Type: " ⊕ A.toText cType
-    where
-      p = do t ← mimeType
-             P.endOfInput
-             return t
 
 -- |Return the value of request header \"Authorization\" as
 -- 'AuthCredential'.
@@ -334,13 +323,9 @@ getAuthorization
            Nothing
                → return Nothing
            Just auth
-               → case P.parseOnly p (A.toByteString auth) of
+               → case P.parseOnly (finishOff authCredential) (A.toByteString auth) of
                     Right ac → return $ Just ac
                     Left  _  → return Nothing
-    where
-      p = do ac ← authCredential
-             P.endOfInput
-             return ac
 
 -- |Tell the system that the 'Resource' found an entity for the
 -- request URI. If this is a GET or HEAD request, a found entity means
@@ -395,21 +380,23 @@ foundETag tag
          -- If-Match があればそれを見る。
          ifMatch ← getHeader "If-Match"
          case ifMatch of
-           Nothing    → return ()
-           Just value → if value ≡ "*" then
-                            return ()
-                        else
-                            case P.parseOnly p (A.toByteString value) of
-                              Right tags
-                                  -- tags の中に一致するものが無ければ
-                                  -- PreconditionFailed で終了。
-                                  → when ((¬) (any (≡ tag) tags))
-                                        $ abort
-                                        $ mkAbortion' PreconditionFailed
-                                        $ "The entity tag doesn't match: " ⊕ A.toText value
-                              Left _
-                                  → abort $ mkAbortion' BadRequest
-                                          $ "Unparsable If-Match: " ⊕ A.toText value
+           Nothing
+               → return ()
+           Just value
+               → if value ≡ "*" then
+                      return ()
+                  else
+                      case P.parseOnly (finishOff eTagList) (A.toByteString value) of
+                        Right tags
+                            -- tags の中に一致するものが無ければ
+                            -- PreconditionFailed で終了。
+                            → when ((¬) (any (≡ tag) tags))
+                                  $ abort
+                                  $ mkAbortion' PreconditionFailed
+                                  $ "The entity tag doesn't match: " ⊕ A.toText value
+                        Left _
+                            → abort $ mkAbortion' BadRequest
+                                    $ "Unparsable If-Match: " ⊕ A.toText value
 
          let statusForNoneMatch
                  = if method ≡ GET ∨ method ≡ HEAD then
@@ -420,26 +407,24 @@ foundETag tag
          -- If-None-Match があればそれを見る。
          ifNoneMatch ← getHeader "If-None-Match"
          case ifNoneMatch of
-           Nothing    → return ()
-           Just value → if value ≡ "*" then
-                            abort $ mkAbortion' statusForNoneMatch
-                                  $ "The entity tag matches: *"
-                        else
-                            case P.parseOnly p (A.toByteString value) of
-                              Right tags
-                                  → when (any (≡ tag) tags)
-                                        $ abort
-                                        $ mkAbortion' statusForNoneMatch
-                                        $ "The entity tag matches: " ⊕ A.toText value
-                              Left _
-                                  → abort $ mkAbortion' BadRequest
-                                          $ "Unparsable If-None-Match: " ⊕ A.toText value
+           Nothing
+               → return ()
+           Just value
+               → if value ≡ "*" then
+                      abort $ mkAbortion' statusForNoneMatch
+                            $ "The entity tag matches: *"
+                  else
+                      case P.parseOnly (finishOff eTagList) (A.toByteString value) of
+                        Right tags
+                            → when (any (≡ tag) tags)
+                                  $ abort
+                                  $ mkAbortion' statusForNoneMatch
+                                  $ "The entity tag matches: " ⊕ A.toText value
+                        Left _
+                            → abort $ mkAbortion' BadRequest
+                                    $ "Unparsable If-None-Match: " ⊕ A.toText value
 
          driftTo ReceivingBody
-    where
-      p = do xs ← eTagList
-             P.endOfInput
-             return xs
 
 -- |Tell the system that the 'Resource' found an entity for the
 -- request URI. The only difference from 'foundEntity' is that