--- #prune
-
--- |Creation and comparison of entity tags.
+{-# LANGUAGE
+ DeriveDataTypeable
+ , FlexibleInstances
+ , MultiParamTypeClasses
+ , OverloadedStrings
+ , RecordWildCards
+ , TemplateHaskell
+ , TypeSynonymInstances
+ , UnicodeSyntax
+ #-}
+-- |An internal module for entity tags.
module Network.HTTP.Lucu.ETag
( ETag(..)
, strongETag
, weakETag
- , eTagP
- , eTagListP
)
where
+import Control.Applicative
+import Data.Ascii (Ascii, AsciiBuilder)
+import Data.Attoparsec.Char8
+import Data.Convertible.Base
+import Data.Convertible.Instances.Ascii ()
+import Data.Convertible.Utils
+import Data.Data
+import Data.Default
+import Data.Monoid.Unicode
+import Language.Haskell.TH.Syntax
+import Network.HTTP.Lucu.OrphanInstances ()
+import Network.HTTP.Lucu.Parser.Http hiding (token)
+import Network.HTTP.Lucu.Utils
+import Prelude.Unicode
-import Control.Monad
-import Network.HTTP.Lucu.Parser
-import Network.HTTP.Lucu.Parser.Http
-import Network.HTTP.Lucu.Utils
-
--- |An entity tag is made of a weakness flag and a opaque string.
+-- |An entity tag consists of a weakness flag and an opaque string.
data ETag = ETag {
- -- |The weakness flag. Weak tags looks like W\/\"blahblah\" and
- -- strong tags are like \"blahblah\".
- etagIsWeak :: Bool
+ -- |The weakness flag. Weak tags looks like @W\/\"blahblah\"@
+ -- and strong tags are like @\"blahblah\"@. See:
+ -- <http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3>
+ etagIsWeak ∷ !Bool
-- |An opaque string. Only characters from 0x20 (sp) to 0x7e (~)
-- are allowed.
- , etagToken :: String
- } deriving (Eq)
-
-instance Show ETag where
- show (ETag isWeak token) = (if isWeak then
- "W/"
- else
- "")
- ++
- quoteStr token
-
--- |This is an equivalent to @'ETag' False@. If you want to generate
--- an ETag from a file, try using
+ , etagToken ∷ !Ascii
+ } deriving (Eq, Show, Data, Typeable)
+
+instance Lift ETag where
+ lift (ETag {..})
+ = [| ETag {
+ etagIsWeak = $(lift etagIsWeak)
+ , etagToken = $(lift etagToken )
+ }
+ |]
+
+instance ConvertSuccess ETag Ascii where
+ {-# INLINE convertSuccess #-}
+ convertSuccess = convertSuccessVia ((⊥) ∷ AsciiBuilder)
+
+instance ConvertSuccess ETag AsciiBuilder where
+ {-# INLINE convertSuccess #-}
+ convertSuccess (ETag {..})
+ = ( if etagIsWeak then
+ cs ("W/" ∷ Ascii)
+ else
+ (∅)
+ )
+ ⊕
+ quoteStr etagToken
+
+deriveAttempts [ ([t| ETag |], [t| Ascii |])
+ , ([t| ETag |], [t| AsciiBuilder |])
+ ]
+
+-- |This is equivalent to @'ETag' 'False'@. If you want to generate an
+-- ETag from a file, try using
-- 'Network.HTTP.Lucu.StaticFile.generateETagFromFile'.
-strongETag :: String -> ETag
+strongETag ∷ Ascii → ETag
+{-# INLINE strongETag #-}
strongETag = ETag False
--- |This is an equivalent to @'ETag' True@.
-weakETag :: String -> ETag
+-- |This is equivalent to @'ETag' 'True'@.
+weakETag ∷ Ascii → ETag
+{-# INLINE weakETag #-}
weakETag = ETag True
+instance Default (Parser ETag) where
+ {-# INLINEABLE def #-}
+ def = do isWeak ← option False (string "W/" *> return True)
+ str ← quotedStr
+ return $ ETag isWeak str
-eTagP :: Parser ETag
-eTagP = do isWeak <- option False (string "W/" >> return True)
- str <- quotedStr
- return $ ETag isWeak str
-
-
-eTagListP :: Parser [ETag]
-eTagListP = allowEOF
- $ do xs <- listOf eTagP
- when (null xs)
- $ fail ""
- return xs
+instance Default (Parser [ETag]) where
+ {-# INLINE def #-}
+ def = listOf def