module Crypto.JOSE.Types.Internal where
import Data.Tuple (swap)
import Data.Aeson.Types
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Base64.URL as B64U
import qualified Data.HashMap.Strict as M
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
objectPairs :: Value -> [Pair]
objectPairs (Object o) = M.toList o
objectPairs _ = []
parseB64 :: FromJSON a => (B.ByteString -> Parser a) -> T.Text -> Parser a
parseB64 f = either fail f . decodeB64
where
decodeB64 = B64.decode . E.encodeUtf8
encodeB64 :: B.ByteString -> Value
encodeB64 = String . E.decodeUtf8 . B64.encode
pad :: B.ByteString -> B.ByteString
pad s = s `B.append` B.replicate ((4 B.length s `mod` 4) `mod` 4) 61
unpad :: B.ByteString -> B.ByteString
unpad = B.reverse . B.dropWhile (== 61) . B.reverse
parseB64Url :: FromJSON a => (B.ByteString -> Parser a) -> T.Text -> Parser a
parseB64Url f = either fail f . B64U.decode . pad . E.encodeUtf8
encodeB64Url :: B.ByteString -> Value
encodeB64Url = String . E.decodeUtf8 . unpad . B64U.encode
bsToInteger :: B.ByteString -> Integer
bsToInteger = B.foldl (\acc x -> acc * 256 + toInteger x) 0
integerToBS :: Integer -> B.ByteString
integerToBS = B.reverse . B.unfoldr (fmap swap . f)
where
f x = if x == 0 then Nothing else Just (toWord8 $ quotRem x 256)
toWord8 (seed, x) = (seed, fromIntegral x)