module System.Environment.Parser.FromEnv (
FromEnv (..)
) where
import Control.Applicative
import Control.Monad
import qualified Data.Aeson as Ae
import qualified Data.Attoparsec.Text as At
import qualified Data.ByteString as S
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy as SL
import qualified Data.ByteString.Lazy.Char8 as SL8
import Data.Int
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Time
import System.Environment.Parser.Class
import System.Locale
class FromEnv a where
parseEnv :: String -> Either String a
fromEnv :: Env r => r String -> r a
fromEnv = joinFailure . fmap parseEnv
instance FromEnv String where
parseEnv = Right
fromEnv = id
instance FromEnv S.ByteString where
parseEnv s = Right (S8.pack s)
fromEnv = fmap S8.pack
instance FromEnv SL.ByteString where
parseEnv s = Right (SL8.pack s)
fromEnv = fmap SL8.pack
instance FromEnv T.Text where
parseEnv s = Right (T.pack s)
fromEnv = fmap T.pack
instance FromEnv TL.Text where
parseEnv s = Right (TL.pack s)
fromEnv = fmap TL.pack
integralEnv :: Integral a => String -> Either String a
integralEnv s = do
txt <- parseEnv s
At.parseOnly (At.signed At.decimal) txt where
instance FromEnv Int where parseEnv = integralEnv
instance FromEnv Integer where parseEnv = integralEnv
instance FromEnv Int8 where parseEnv = integralEnv
instance FromEnv Int64 where parseEnv = integralEnv
instance FromEnv Int32 where parseEnv = integralEnv
instance FromEnv Int16 where parseEnv = integralEnv
instance FromEnv Double where
parseEnv s = do
txt <- parseEnv s
At.parseOnly (At.signed At.double) txt
instance FromEnv At.Number where
parseEnv s = do
txt <- parseEnv s
At.parseOnly (At.signed At.number) txt
instance FromEnv DiffTime where
parseEnv s =
realToFrac <$> (parseEnv s :: Either String At.Number)
instance FromEnv NominalDiffTime where
parseEnv s =
realToFrac <$> (parseEnv s :: Either String At.Number)
instance FromEnv UTCTime where
parseEnv s =
e "bad UTC time"
$ msum $ map (\format -> parseTime defaultTimeLocale format s) formats
where
formats =
[ "%Y-%m-%dT%H:%M:%S%Q%z"
, "%Y-%m-%dT%H:%M:%S%QZ"
, "%a %b %_d %H:%M:%S %z %Y"
, "%a %b %_d %H:%M:%S %Y"
, "%b %_d %H:%M:%S %Y"
]
instance FromEnv Day where
parseEnv s =
e "bad date" $ parseTime defaultTimeLocale "%Y-%m-%d" s
instance FromEnv Ae.Value where
parseEnv s = do
bs <- parseEnv s
Ae.eitherDecodeStrict bs
e :: String -> Maybe a -> Either String a
e s Nothing = Left s
e _ (Just a) = Right a