]> gitweb @ CieloNegro.org - time-http.git/blobdiff - Data/Time/HTTP/Common.hs
Fix build error
[time-http.git] / Data / Time / HTTP / Common.hs
index bb4ac16527c0ac6768eb22c097fbd46a97f355a1..c98338988bdaf17e7d69fb1a8b92d0a4de2e8e46 100644 (file)
@@ -15,11 +15,13 @@ module Data.Time.HTTP.Common
     , longMonthName
     , longMonthNameP
 
-    , show2
     , show4
+    , show2
+    , show2'
 
-    , read2
     , read4
+    , read2
+    , read2'
 
     , show4digitsTZ
     , read4digitsTZ
@@ -29,31 +31,43 @@ module Data.Time.HTTP.Common
     , assertTimeOfDayIsGood
 
     , optionMaybe
+    , finishOff
+
+    , parseAttempt
+    , parseAttempt'
     )
     where
 import Blaze.ByteString.Builder.ByteString as B
 import Blaze.Text.Int as BT
 import Control.Applicative
+import Control.Exception.Base
 import Control.Monad
-import Data.Ascii (AsciiBuilder)
+import Control.Monad.Unicode
+import Data.Ascii (Ascii, AsciiBuilder)
 import qualified Data.Ascii as A
+import Data.Attempt
 import Data.Attoparsec.Char8 as P
+import Data.ByteString (ByteString)
+import Data.Char
 import Data.Monoid.Unicode
 import Data.Fixed
 import Data.Time
 import Data.Time.Calendar.WeekDate
 import Prelude.Unicode
 
-shortWeekDayName ∷ Num n ⇒ n → String
-{-# INLINEABLE shortWeekDayName #-}
-shortWeekDayName 1 = "Mon"
-shortWeekDayName 2 = "Tue"
-shortWeekDayName 3 = "Wed"
-shortWeekDayName 4 = "Thu"
-shortWeekDayName 5 = "Fri"
-shortWeekDayName 6 = "Sat"
-shortWeekDayName 7 = "Sun"
-shortWeekDayName n = error ("shortWeekDayName: invalid week day: " ⧺ show n)
+shortWeekDayName ∷ Num n ⇒ n → AsciiBuilder
+{-# INLINE shortWeekDayName #-}
+shortWeekDayName = A.toAsciiBuilder ∘ go
+    where
+      {-# INLINEABLE go #-}
+      go 1 = "Mon"
+      go 2 = "Tue"
+      go 3 = "Wed"
+      go 4 = "Thu"
+      go 5 = "Fri"
+      go 6 = "Sat"
+      go 7 = "Sun"
+      go n = error ("shortWeekDayName: invalid week day: " ⧺ show n)
 
 shortWeekDayNameP ∷ Num n ⇒ Parser n
 {-# INLINEABLE shortWeekDayNameP #-}
@@ -71,16 +85,19 @@ shortWeekDayNameP
                          ]
              ]
 
-longWeekDayName ∷ Num n ⇒ n → String
-{-# INLINEABLE longWeekDayName #-}
-longWeekDayName 1 = "Monday"
-longWeekDayName 2 = "Tuesday"
-longWeekDayName 3 = "Wednesday"
-longWeekDayName 4 = "Thursday"
-longWeekDayName 5 = "Friday"
-longWeekDayName 6 = "Saturday"
-longWeekDayName 7 = "Sunday"
-longWeekDayName n = error ("longWeekDayName: invalid week day: " ⧺ show n)
+longWeekDayName ∷ Num n ⇒ n → AsciiBuilder
+{-# INLINE longWeekDayName #-}
+longWeekDayName = A.toAsciiBuilder ∘ go
+    where
+      {-# INLINEABLE go #-}
+      go 1 = "Monday"
+      go 2 = "Tuesday"
+      go 3 = "Wednesday"
+      go 4 = "Thursday"
+      go 5 = "Friday"
+      go 6 = "Saturday"
+      go 7 = "Sunday"
+      go n = error ("longWeekDayName: invalid week day: " ⧺ show n)
 
 longWeekDayNameP ∷ Num n ⇒ Parser n
 {-# INLINEABLE longWeekDayNameP #-}
@@ -98,21 +115,24 @@ longWeekDayNameP
                          ]
              ]
 
-shortMonthName ∷ Num n ⇒ n → String
-{-# INLINEABLE shortMonthName #-}
-shortMonthName  1 = "Jan"
-shortMonthName  2 = "Feb"
-shortMonthName  3 = "Mar"
-shortMonthName  4 = "Apr"
-shortMonthName  5 = "May"
-shortMonthName  6 = "Jun"
-shortMonthName  7 = "Jul"
-shortMonthName  8 = "Aug"
-shortMonthName  9 = "Sep"
-shortMonthName 10 = "Oct"
-shortMonthName 11 = "Nov"
-shortMonthName 12 = "Dec"
-shortMonthName  n = error ("shortMonthName: invalid month: " ⧺ show n)
+shortMonthName ∷ Num n ⇒ n → AsciiBuilder
+{-# INLINE shortMonthName #-}
+shortMonthName = A.toAsciiBuilder ∘ go
+    where
+      {-# INLINEABLE go #-}
+      go  1 = "Jan"
+      go  2 = "Feb"
+      go  3 = "Mar"
+      go  4 = "Apr"
+      go  5 = "May"
+      go  6 = "Jun"
+      go  7 = "Jul"
+      go  8 = "Aug"
+      go  9 = "Sep"
+      go 10 = "Oct"
+      go 11 = "Nov"
+      go 12 = "Dec"
+      go  n = error ("shortMonthName: invalid month: " ⧺ show n)
 
 shortMonthNameP ∷ Num n ⇒ Parser n
 {-# INLINEABLE shortMonthNameP #-}
@@ -139,21 +159,24 @@ shortMonthNameP
              , string "Dec" *> return 12
              ]
 
-longMonthName ∷ Num n ⇒ n → String
-{-# INLINEABLE longMonthName #-}
-longMonthName  1 = "January"
-longMonthName  2 = "February"
-longMonthName  3 = "March"
-longMonthName  4 = "April"
-longMonthName  5 = "May"
-longMonthName  6 = "June"
-longMonthName  7 = "July"
-longMonthName  8 = "August"
-longMonthName  9 = "September"
-longMonthName 10 = "October"
-longMonthName 11 = "November"
-longMonthName 12 = "December"
-longMonthName  n = error ("longMonthName: invalid month: " ⧺ show n)
+longMonthName ∷ Num n ⇒ n → AsciiBuilder
+{-# INLINE longMonthName #-}
+longMonthName = A.toAsciiBuilder ∘ go
+    where
+      {-# INLINEABLE go #-}
+      go  1 = "January"
+      go  2 = "February"
+      go  3 = "March"
+      go  4 = "April"
+      go  5 = "May"
+      go  6 = "June"
+      go  7 = "July"
+      go  8 = "August"
+      go  9 = "September"
+      go 10 = "October"
+      go 11 = "November"
+      go 12 = "December"
+      go  n = error ("longMonthName: invalid month: " ⧺ show n)
 
 longMonthNameP ∷ Num n ⇒ Parser n
 {-# INLINEABLE longMonthNameP #-}
@@ -199,6 +222,14 @@ show2 = A.unsafeFromBuilder ∘ go
            | i ≥ 0 ∧ i < 100 =                        BT.integral i
            | otherwise       = error ("show2: the integer i must satisfy 0 <= i < 100: " ⧺ show i)
 
+show2' ∷ Integral i ⇒ i → AsciiBuilder
+{-# INLINE show2' #-}
+show2' = A.unsafeFromBuilder ∘ go
+    where
+      go i | i ≥ 0 ∧ i < 10  = B.fromByteString " " ⊕ BT.digit    i
+           | i ≥ 0 ∧ i < 100 =                        BT.integral i
+           | otherwise       = error ("show2': the integer i must satisfy 0 <= i < 100: " ⧺ show i)
+
 read4 ∷ Num n ⇒ Parser n
 {-# INLINEABLE read4 #-}
 read4 = do n1 ← digit'
@@ -213,23 +244,21 @@ read2 = do n1 ← digit'
            n2 ← digit'
            return (n1 * 10 + n2)
 
+read2' ∷ Num n ⇒ Parser n
+{-# INLINEABLE read2' #-}
+read2' = do n1 ← (char ' ' *> pure 0) <|> digit'
+            n2 ← digit'
+            return (n1 * 10 + n2)
+
 digit' ∷ Num n ⇒ Parser n
-digit' = fromC <$> P.digit
-
-fromC ∷ Num n ⇒ Char → n
-fromC '0' = 0
-fromC '1' = 1
-fromC '2' = 2
-fromC '3' = 3
-fromC '4' = 4
-fromC '5' = 5
-fromC '6' = 6
-fromC '7' = 7
-fromC '8' = 8
-fromC '9' = 9
-fromC _   = undefined
+{-# INLINE digit' #-}
+digit' = fromIntegral <$> fromC <$> P.digit
+    where
+      {-# INLINE fromC #-}
+      fromC c = ord c - ord '0'
 
 show4digitsTZ ∷ TimeZone → AsciiBuilder
+{-# INLINEABLE show4digitsTZ #-}
 show4digitsTZ tz
     = case timeZoneMinutes tz of
         offset | offset <  0 → A.toAsciiBuilder "-" ⊕ showTZ' (negate offset)
@@ -242,6 +271,7 @@ show4digitsTZ tz
               show2 h ⊕ show2 m
 
 read4digitsTZ ∷ Parser TimeZone
+{-# INLINEABLE read4digitsTZ #-}
 read4digitsTZ
     = do sign   ← (char '+' *> return 1)
                   <|>
@@ -262,7 +292,7 @@ assertWeekDayIsGood givenWD gregDay
           (year, month, day) = toGregorian gregDay
       in
         unless (givenWD ≡ correctWD)
-            $ fail
+             fail
             $ concat [ "Gregorian day "
                      , show year
                      , "-"
@@ -270,10 +300,13 @@ assertWeekDayIsGood givenWD gregDay
                      , "-"
                      , show day
                      , " is "
-                     , longWeekDayName correctWD
+                     , toStr $ longWeekDayName correctWD
                      , ", not "
-                     , longWeekDayName givenWD
+                     , toStr $ longWeekDayName givenWD
                      ]
+    where
+      toStr ∷ AsciiBuilder → String
+      toStr = A.toString ∘ A.fromAsciiBuilder
 
 assertGregorianDateIsGood ∷ Monad m ⇒ Integer → Int → Int → m Day
 {-# INLINEABLE assertGregorianDateIsGood #-}
@@ -309,3 +342,22 @@ optionMaybe ∷ Alternative f ⇒ f a → f (Maybe a)
 {-# INLINE optionMaybe #-}
 optionMaybe p
     = option Nothing (Just <$> p)
+
+finishOff ∷ Parser α → Parser α
+{-# INLINE finishOff #-}
+finishOff = ((endOfInput *>) ∘ return =≪)
+
+parseAttempt ∷ Exception e
+             ⇒ (String → e)
+             → Parser α
+             → ByteString
+             → Attempt α
+{-# INLINEABLE parseAttempt #-}
+parseAttempt f p bs
+    = case parseOnly (finishOff p) bs of
+        Right α → Success α
+        Left  e → Failure $ f e
+
+parseAttempt' ∷ Parser α → Ascii → Attempt α
+{-# INLINE parseAttempt' #-}
+parseAttempt' = (∘ A.toByteString) ∘ parseAttempt StringException