{-# LANGUAGE DeriveDataTypeable , FlexibleInstances , MultiParamTypeClasses , OverloadedStrings , RecordWildCards , TemplateHaskell , UnicodeSyntax #-} -- |An internal module for entity tags. module Network.HTTP.Lucu.ETag ( ETag(..) , strongETag , weakETag ) where import Control.Applicative import Control.Monad import Data.Ascii (Ascii, AsciiBuilder) import Data.Attoparsec.Char8 import Data.Attoparsec.Parsable import Data.ByteString (ByteString) import Data.Convertible.Base import Data.Convertible.Instances.Ascii () import Data.Convertible.Utils import Data.Data 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 -- |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\"@. See: -- etagIsWeak ∷ !Bool -- |An opaque string. Only characters from 0x20 (sp) to 0x7e (~) -- are allowed. , 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 ∷ Ascii → ETag {-# INLINE strongETag #-} strongETag = ETag False -- |This is equivalent to @'ETag' 'True'@. weakETag ∷ Ascii → ETag {-# INLINE weakETag #-} weakETag = ETag True instance Parsable ByteString ETag where {-# INLINEABLE parser #-} parser = do isWeak ← option False (string "W/" *> return True) str ← quotedStr return $ ETag isWeak str instance Parsable ByteString [ETag] where {-# INLINEABLE parser #-} parser = do xs ← listOf parser when (null xs) $ fail "empty list of ETags" return xs