diff options
Diffstat (limited to 'lib/Postdelay/Scan.hs')
-rw-r--r-- | lib/Postdelay/Scan.hs | 43 |
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 | |||
3 | module Postdelay.Scan | ||
4 | ( scan | ||
5 | , Delay(..) | ||
6 | , ParseError(..) | ||
7 | ) where | ||
8 | |||
9 | import Postdelay.Types | ||
10 | import Postdelay.Utils | ||
11 | import Postdelay.TimeSpec | ||
12 | |||
13 | import Control.Monad | ||
14 | import Control.Monad.IO.Class | ||
15 | import Control.Monad.Error.Class | ||
16 | |||
17 | import Text.Parsec.Char | ||
18 | import Text.Parsec.Prim | ||
19 | import Text.Parsec.Combinator | ||
20 | import Text.Parsec.Error (ParseError(..)) | ||
21 | import Text.ParserCombinators.Parsec.Rfc2822 | ||
22 | |||
23 | import Data.CaseInsensitive (CI) | ||
24 | import qualified Data.CaseInsensitive as CI | ||
25 | |||
26 | import Data.Either | ||
27 | import Data.Foldable | ||
28 | import Data.Semigroup | ||
29 | |||
30 | |||
31 | scan :: (MonadIO m, MonadError ParseError m) => String -> m (Maybe Delay) | ||
32 | scan = fmap getOption . extractDelay <=< either throwError return . parse message "" | ||
33 | |||
34 | extractDelay :: forall m. (MonadIO m, MonadError ParseError m) => Message -> m (Option Delay) | ||
35 | extractDelay (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 | ||