]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Implant/PrettyPrint.hs
ImplantFile started working again.
[Lucu.git] / Network / HTTP / Lucu / Implant / PrettyPrint.hs
diff --git a/Network/HTTP/Lucu/Implant/PrettyPrint.hs b/Network/HTTP/Lucu/Implant/PrettyPrint.hs
new file mode 100644 (file)
index 0000000..027003d
--- /dev/null
@@ -0,0 +1,213 @@
+{-# LANGUAGE
+    DoAndIfThenElse
+  , OverloadedStrings
+  , RecordWildCards
+  , TemplateHaskell
+  , UnicodeSyntax
+  #-}
+module Network.HTTP.Lucu.Implant.PrettyPrint
+    ( pprInput
+    )
+    where
+import Codec.Compression.GZip
+import Control.Monad
+import Data.Ascii (CIAscii)
+import qualified Data.Ascii as A
+import qualified Data.ByteString.Lazy as L
+import Data.List
+import qualified Data.Map as M
+import Data.Time
+import Language.Haskell.TH.Lib
+import Language.Haskell.TH.Ppr
+import Language.Haskell.TH.PprLib
+import Language.Haskell.TH.Syntax
+import Network.HTTP.Lucu.ETag
+import Network.HTTP.Lucu.Implant.Input
+import Network.HTTP.Lucu.Implant.Rewrite
+import Network.HTTP.Lucu.MIMEType
+import Network.HTTP.Lucu.Resource
+import Network.HTTP.Lucu.Utils
+import Prelude.Unicode
+
+header ∷ Input → Doc
+header i@(Input {..})
+    = vcat [ text "{- DO NOT EDIT THIS FILE."
+           , nest 3 $
+             vcat [ text "This file is automatically generated by lucu-implant-file."
+                  , text ""
+                  , text "           Source:" <+> if iPath ≡ "-" then
+                                                      text "(stdin)"
+                                                  else
+                                                      text iPath
+                  , hsep [ text "  Original Length:"
+                         , integer (originalLen i)
+                         , text "bytes"
+                         ]
+                  , if useGZip i then
+                        vcat [ hsep [ text "Compressed Length:"
+                                    , integer (gzippedLen i)
+                                    , text "bytes"
+                                    ]
+                             , text "      Compression: gzip"
+                             ]
+                    else
+                        text "      Compression: disabled"
+                  , text "        MIME Type:" <+> mimeTypeToDoc iType
+                  , text "             ETag:" <+> eTagToDoc iETag
+                  , text "    Last Modified:" <+> text (show iLastMod)
+                  ]
+           , text " -}"
+           , text "{-# LANGUAGE MagicHash #-}"
+           ]
+    where
+      eTagToDoc ∷ ETag → Doc
+      eTagToDoc = text ∘ A.toString ∘ A.fromAsciiBuilder ∘ printETag
+
+      mimeTypeToDoc ∷ MIMEType → Doc
+      mimeTypeToDoc = text ∘ A.toString ∘ A.fromAsciiBuilder ∘ printMIMEType
+
+moduleDecl ∷ ModName → Name → Doc
+moduleDecl modName symName
+    = hsep [ text "module"
+           , text (modString modName)
+           , lparen
+           , ppr symName
+           , rparen
+           , text "where"
+           ]
+
+importDecls ∷ ModMap → Doc
+importDecls = vcat ∘ map f ∘ M.toAscList
+    where
+      f ∷ (ModName, Maybe ModName) → Doc
+      f (m, Nothing) = hsep [ text "import"
+                            , text (modString m)
+                            ]
+      f (m, Just m') = hsep [ text "import"
+                            , text "qualified"
+                            , text (modString m)
+                            , text "as"
+                            , text (modString m')
+                            ]
+
+entityTag ∷ Name
+entityTag = mkName "entityTag"
+
+lastModified ∷ Name
+lastModified = mkName "lastModified"
+
+contentType ∷ Name
+contentType = mkName "contentType"
+
+rawData ∷ Name
+rawData = mkName "rawData"
+
+gzippedData ∷ Name
+gzippedData = mkName "gzippedData"
+
+gzipEncoding ∷ Name
+gzipEncoding = mkName "gzipEncoding"
+
+resourceDecl ∷ Input → Name → Q [Dec]
+resourceDecl i symName
+    = sequence [ sigD symName [t| ResourceDef |]
+               , valD (varP symName) (normalB (resourceE i)) decls
+               ]
+    where
+      decls ∷ [Q Dec]
+      decls | useGZip i
+                = [ sigD gzipEncoding [t| CIAscii |]
+                  , valD (varP gzipEncoding) (normalB (liftCIAscii "gzip")) []
+                  ]
+            | otherwise
+                = []
+
+resourceE ∷ Input → Q Exp
+resourceE i = [| emptyResource {
+                   resGet  = $(resGetE  i)
+                 , resHead = $(resHeadE i)
+                 }
+               |]
+
+resGetE ∷ Input → Q Exp
+resGetE i
+    | useGZip i
+        = [| Just $
+             do foundEntity $(varE entityTag) $(varE lastModified)
+                setContentType $(varE contentType)
+
+                gzipAllowed ← isEncodingAcceptable $(varE gzipEncoding)
+                if gzipAllowed then
+                    do setContentEncoding [$(varE gzipEncoding)]
+                       putChunks $(varE gzippedData)
+                else
+                    putChunks (decompress $(varE gzippedData))
+           |]
+    | otherwise
+        = [| Just $
+             do foundEntity $(varE entityTag) $(varE lastModified)
+                setContentType $(varE contentType)
+                putChunks $(varE rawData)
+           |]
+
+resHeadE ∷ Input → Q Exp
+resHeadE i
+    | useGZip i
+        = [| Just $
+             do foundEntity $(varE entityTag) $(varE lastModified)
+                setContentType $(varE contentType)
+
+                gzipAllowed ← isEncodingAcceptable $(varE gzipEncoding)
+                when gzipAllowed (setContentEncoding [$(varE gzipEncoding)])
+           |]
+    | otherwise
+        = [| Just $
+             do foundEntity $(varE entityTag)
+                            $(varE lastModified)
+                setContentType $(varE contentType)
+           |]
+
+eTagDecl ∷ Input → Q [Dec]
+eTagDecl (Input {..})
+    = sequence [ sigD entityTag [t| ETag |]
+               , valD (varP entityTag) (normalB (lift iETag)) []
+               ]
+
+lastModDecl ∷ Input → Q [Dec]
+lastModDecl (Input {..})
+    = sequence [ sigD lastModified [t| UTCTime |]
+               , valD (varP lastModified) (normalB (liftUTCTime iLastMod)) []
+               ]
+
+contTypeDecl ∷ Input → Q [Dec]
+contTypeDecl (Input {..})
+    = sequence [ sigD contentType [t| MIMEType |]
+               , valD (varP contentType) (normalB (lift iType)) []
+               ]
+
+binDecl ∷ Input → Q [Dec]
+binDecl i@(Input {..})
+    | useGZip i
+        = sequence [ sigD gzippedData [t| L.ByteString |]
+                   , valD (varP gzippedData) (normalB (liftLazyByteString iGZipped)) []
+                   ]
+    | otherwise
+        = sequence [ sigD rawData [t| L.ByteString |]
+                   , valD (varP rawData) (normalB (liftLazyByteString iRawData)) []
+                   ]
+
+pprInput ∷ Quasi m ⇒ Input → ModName → Name → m Doc
+pprInput i modName symName
+    = do decls ← runQ $ sequence [ resourceDecl i symName
+                                 , eTagDecl i
+                                 , lastModDecl i
+                                 , contTypeDecl i
+                                 , binDecl i
+                                 ]
+         let (decls', mods) = rewriteNames decls
+         return $ vcat [ header i
+                       , moduleDecl modName symName
+                       , importDecls mods
+                       , text ""
+                       , vcat $ intersperse (text "") $ map ppr decls'
+                       ]