summaryrefslogtreecommitdiff
path: root/lib/Postdelay/Scan.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Postdelay/Scan.hs')
-rw-r--r--lib/Postdelay/Scan.hs43
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/Postdelay/Scan.hs b/lib/Postdelay/Scan.hs
new file mode 100644
index 0000000..e6de0cf
--- /dev/null
+++ b/lib/Postdelay/Scan.hs
@@ -0,0 +1,43 @@
1{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, FlexibleContexts #-}
2
3module Postdelay.Scan
4 ( scan
5 , Delay(..)
6 , ParseError(..)
7 ) where
8
9import Postdelay.Types
10import Postdelay.Utils
11import Postdelay.TimeSpec
12
13import Control.Monad
14import Control.Monad.IO.Class
15import Control.Monad.Error.Class
16
17import Text.Parsec.Char
18import Text.Parsec.Prim
19import Text.Parsec.Combinator
20import Text.Parsec.Error (ParseError(..))
21import Text.ParserCombinators.Parsec.Rfc2822
22
23import Data.CaseInsensitive (CI)
24import qualified Data.CaseInsensitive as CI
25
26import Data.Either
27import Data.Foldable
28import Data.Semigroup
29
30
31scan :: (MonadIO m, MonadError ParseError m) => String -> m (Maybe Delay)
32scan = fmap getOption . extractDelay <=< either throwError return . parse message ""
33
34extractDelay :: forall m. (MonadIO m, MonadError ParseError m) => Message -> m (Option Delay)
35extractDelay (Message headers _) = foldMap pure <$> mapM parseDelay delayHeaders
36 where
37 delayHeaders :: [Field]
38 delayHeaders = do
39 h@(OptionalField field content) <- headers
40 guard $ CI.mk field == "X-Delay"
41 return h
42 parseDelay :: Field -> m Delay
43 parseDelay (OptionalField field content) = either throwError return =<< runParserT (Until <$> pTimeSpec) () field content