X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=time-http.git;a=blobdiff_plain;f=Data%2FTime%2FHTTP%2FCommon.hs;h=1cfa89e9c63528268d721d309927dc58f981f586;hp=6a45805ed80be61aa996c7351554b7f82689b9d5;hb=e322e3c65458dd6004ae4d2fbf5e82ce9aaee162;hpb=d39ace5728c981d8c9d83fe8eefcd811dbb1e8aa diff --git a/Data/Time/HTTP/Common.hs b/Data/Time/HTTP/Common.hs index 6a45805..1cfa89e 100644 --- a/Data/Time/HTTP/Common.hs +++ b/Data/Time/HTTP/Common.hs @@ -15,11 +15,13 @@ module Data.Time.HTTP.Common , longMonthName , longMonthNameP - , show2 , show4 + , show2 + , show2' - , read2 , read4 + , read2 + , read2' , show4digitsTZ , read4digitsTZ @@ -27,13 +29,14 @@ module Data.Time.HTTP.Common , assertWeekDayIsGood , assertGregorianDateIsGood , assertTimeOfDayIsGood + + , optionMaybe ) where import Blaze.ByteString.Builder.ByteString as B import Blaze.Text.Int as BT import Control.Applicative import Control.Monad -import Control.Monad.Unicode import Data.Ascii (AsciiBuilder) import qualified Data.Ascii as A import Data.Attoparsec.Char8 as P @@ -43,140 +46,152 @@ 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 #-} shortWeekDayNameP - = choice [ string "Mon" ≫ return 1 + = choice [ string "Mon" *> return 1 , char 'T' - ≫ choice [ string "ue" ≫ return 2 - , string "hu" ≫ return 4 - ] - , string "Wed" ≫ return 3 - , string "Fri" ≫ return 5 + *> choice [ string "ue" *> return 2 + , string "hu" *> return 4 + ] + , string "Wed" *> return 3 + , string "Fri" *> return 5 , char 'S' - ≫ choice [ string "at" ≫ return 6 - , string "un" ≫ return 7 - ] + *> choice [ string "at" *> return 6 + , string "un" *> return 7 + ] ] -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 #-} longWeekDayNameP - = choice [ string "Monday" ≫ return 1 + = choice [ string "Monday" *> return 1 , char 'T' - ≫ choice [ string "uesday" ≫ return 2 - , string "hursday" ≫ return 4 - ] - , string "Wednesday" ≫ return 3 - , string "Friday" ≫ return 5 + *> choice [ string "uesday" *> return 2 + , string "hursday" *> return 4 + ] + , string "Wednesday" *> return 3 + , string "Friday" *> return 5 , char 'S' - ≫ choice [ string "aturday" ≫ return 6 - , string "unday" ≫ return 7 - ] + *> choice [ string "aturday" *> return 6 + , string "unday" *> return 7 + ] ] -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 #-} shortMonthNameP = choice [ char 'J' - ≫ choice [ string "an" ≫ return 1 - , char 'u' - ≫ choice [ char 'n' ≫ return 6 - , char 'l' ≫ return 7 - ] - ] - , string "Feb" ≫ return 2 + *> choice [ string "an" *> return 1 + , char 'u' + *> choice [ char 'n' *> return 6 + , char 'l' *> return 7 + ] + ] + , string "Feb" *> return 2 , string "Ma" - ≫ choice [ char 'r' ≫ return 3 - , char 'y' ≫ return 5 - ] + *> choice [ char 'r' *> return 3 + , char 'y' *> return 5 + ] , char 'A' - ≫ choice [ string "pr" ≫ return 4 - , string "ug" ≫ return 8 - ] - , string "Sep" ≫ return 9 - , string "Oct" ≫ return 10 - , string "Nov" ≫ return 11 - , string "Dec" ≫ return 12 + *> choice [ string "pr" *> return 4 + , string "ug" *> return 8 + ] + , string "Sep" *> return 9 + , string "Oct" *> return 10 + , string "Nov" *> return 11 + , 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 #-} longMonthNameP = choice [ char 'J' - ≫ choice [ string "anuary" ≫ return 1 - , char 'u' - ≫ choice [ string "ne" ≫ return 6 - , string "ly" ≫ return 7 - ] - ] - , string "February" ≫ return 2 + *> choice [ string "anuary" *> return 1 + , char 'u' + *> choice [ string "ne" *> return 6 + , string "ly" *> return 7 + ] + ] + , string "February" *> return 2 , string "Ma" - ≫ choice [ string "rch" ≫ return 3 - , char 'y' ≫ return 5 - ] + *> choice [ string "rch" *> return 3 + , char 'y' *> return 5 + ] , char 'A' - ≫ choice [ string "pril" ≫ return 4 - , string "ugust" ≫ return 8 - ] - , string "September" ≫ return 9 - , string "October" ≫ return 10 - , string "November" ≫ return 11 - , string "December" ≫ return 12 + *> choice [ string "pril" *> return 4 + , string "ugust" *> return 8 + ] + , string "September" *> return 9 + , string "October" *> return 10 + , string "November" *> return 11 + , string "December" *> return 12 ] show4 ∷ Integral i ⇒ i → AsciiBuilder @@ -198,6 +213,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' @@ -212,6 +235,12 @@ 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 @@ -242,9 +271,9 @@ show4digitsTZ tz read4digitsTZ ∷ Parser TimeZone read4digitsTZ - = do sign ← (char '+' ≫ return 1) + = do sign ← (char '+' *> return 1) <|> - (char '-' ≫ return (-1)) + (char '-' *> return (-1)) hour ← read2 minute ← read2 let tz = TimeZone { @@ -269,10 +298,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 #-} @@ -303,3 +335,8 @@ assertTimeOfDayIsGood hour minute second ] Just tod → return tod + +optionMaybe ∷ Alternative f ⇒ f a → f (Maybe a) +{-# INLINE optionMaybe #-} +optionMaybe p + = option Nothing (Just <$> p)