]> gitweb @ CieloNegro.org - Lucu.git/blob - Network/HTTP/Lucu/ETag.hs
code cleanup
[Lucu.git] / Network / HTTP / Lucu / ETag.hs
1 {-# LANGUAGE
2     OverloadedStrings
3   , UnicodeSyntax
4   #-}
5 -- |Entity tags
6 module Network.HTTP.Lucu.ETag
7     ( ETag(..)
8     , parseETag
9     , printETag
10
11     , strongETag
12     , weakETag
13     , eTag
14     , eTagList
15     )
16     where
17 import Control.Applicative
18 import Control.Monad
19 import Data.Ascii (Ascii, AsciiBuilder)
20 import qualified Data.Ascii as A
21 import Data.Attoparsec.Char8
22 import Data.Monoid.Unicode
23 import Network.HTTP.Lucu.Parser
24 import Network.HTTP.Lucu.Parser.Http hiding (token)
25 import Network.HTTP.Lucu.Utils
26 import Prelude.Unicode
27
28 -- |An entity tag consists of a weakness flag and an opaque string.
29 data ETag = ETag {
30       -- |The weakness flag. Weak tags looks like W\/\"blahblah\" and
31       -- strong tags are like \"blahblah\". See:
32       -- <http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3>
33       etagIsWeak ∷ !Bool
34       -- |An opaque string. Only characters from 0x20 (sp) to 0x7e (~)
35       -- are allowed.
36     , etagToken  ∷ !Ascii
37     } deriving (Eq, Show)
38
39 -- |Convert an 'ETag' to an 'AsciiBuilder'.
40 printETag ∷ ETag → AsciiBuilder
41 {-# INLINEABLE printETag #-}
42 printETag et
43     = ( if etagIsWeak et then
44             A.toAsciiBuilder "W/"
45         else
46             (∅)
47       )
48       ⊕
49       quoteStr (etagToken et)
50
51 -- |Parse 'Etag' from an 'Ascii'. This functions throws an exception
52 -- for parse error.
53 parseETag ∷ Ascii → ETag
54 {-# INLINEABLE parseETag #-}
55 parseETag str
56     = case parseOnly (finishOff eTag) $ A.toByteString str of
57         Right et → et
58         Left err → error ("unparsable ETag: " ⧺ A.toString str ⧺ ": " ⧺ err)
59
60 -- |This is equivalent to @'ETag' 'False'@. If you want to generate an
61 -- ETag from a file, try using
62 -- 'Network.HTTP.Lucu.StaticFile.generateETagFromFile'.
63 strongETag ∷ Ascii → ETag
64 {-# INLINE strongETag #-}
65 strongETag = ETag False
66
67 -- |This is equivalent to @'ETag' 'True'@.
68 weakETag ∷ Ascii → ETag
69 {-# INLINE weakETag #-}
70 weakETag = ETag True
71
72 -- |'Parser' for an 'ETag'.
73 eTag ∷ Parser ETag
74 {-# INLINEABLE eTag #-}
75 eTag = do isWeak ← option False (string "W/" *> return True)
76           str    ← quotedStr
77           return $ ETag isWeak str
78
79 -- |'Parser' for a list of 'ETag's.
80 eTagList ∷ Parser [ETag]
81 {-# INLINEABLE eTagList #-}
82 eTagList = do xs ← listOf eTag
83               when (null xs) $
84                   fail "empty list of ETags"
85               return xs