module Network.Iron.Util (
b64
, b64dec
, b64url
, b64urldec
, urlSafeBase64
, unUrlSafeBase64
, parseExpMsec
, justRight
, rightJust
, mapLeft
) where
import Crypto.Hash
import Data.ByteArray (ByteArrayAccess)
import qualified Data.ByteArray.Encoding as B (Base (..), convertToBase, convertFromBase)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS (pack, unpack)
import qualified Data.ByteString.Char8 as S8
import Data.Monoid ((<>))
import Data.Time.Clock (NominalDiffTime)
import Text.Read (readMaybe)
b64 :: ByteArrayAccess a => a -> ByteString
b64 = B.convertToBase B.Base64
b64url :: ByteArrayAccess a => a -> ByteString
b64url = urlSafeBase64 . b64
b64dec :: ByteArrayAccess a => a -> Either String ByteString
b64dec = B.convertFromBase B.Base64
b64urldec :: ByteString -> Either String ByteString
b64urldec = b64dec . unUrlSafeBase64
urlSafeBase64 :: ByteString -> ByteString
urlSafeBase64 = S8.filter (/= '=') . S8.map (tr '+' '-' . tr '/' '_')
where
tr a b c = if c == a then b else c
unUrlSafeBase64 :: ByteString -> ByteString
unUrlSafeBase64 = pad . S8.map (tr '-' '+' . tr '_' '/')
where
tr a b c = if c == a then b else c
pad s = s <> S8.replicate (S8.length s `mod` 4) '='
parseExpMsec :: ByteString -> Maybe NominalDiffTime
parseExpMsec = (>>= fromMsec . guard) . readMaybe . S8.unpack
where
fromMsec = fmap ((/ 1000) . fromInteger)
guard n | n > 0 = Just n
| otherwise = Nothing
rightJust :: Either e a -> Maybe a
rightJust (Right a) = Just a
rightJust _ = Nothing
justRight :: e -> Maybe a -> Either e a
justRight _ (Just a) = Right a
justRight e Nothing = Left e
mapLeft :: (e -> e') -> Either e a -> Either e' a
mapLeft f (Left e) = Left (f e)
mapLeft _ (Right a) = Right a