{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}

module Data.ByteArray.Base64String where

import           Data.Aeson              (FromJSON (..), ToJSON (..),
                                          Value (..), withText)
import           Data.ByteArray          (ByteArray, ByteArrayAccess, convert)
import           Data.ByteArray.Encoding (Base (Base64), convertFromBase,
                                          convertToBase)
import           Data.ByteString         (ByteString)
import           Data.String             (IsString (..))
import           Data.Text               (Text)
import           Data.Text.Encoding      (decodeUtf8, encodeUtf8)


-- | Represents a Hex string. Guarantees that all characters it contains
--   are valid hex characters.
newtype Base64String = Base64String { Base64String -> ByteString
unBase64String :: ByteString }
  deriving (Base64String -> Base64String -> Bool
(Base64String -> Base64String -> Bool)
-> (Base64String -> Base64String -> Bool) -> Eq Base64String
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64String -> Base64String -> Bool
$c/= :: Base64String -> Base64String -> Bool
== :: Base64String -> Base64String -> Bool
$c== :: Base64String -> Base64String -> Bool
Eq, Eq Base64String
Eq Base64String =>
(Base64String -> Base64String -> Ordering)
-> (Base64String -> Base64String -> Bool)
-> (Base64String -> Base64String -> Bool)
-> (Base64String -> Base64String -> Bool)
-> (Base64String -> Base64String -> Bool)
-> (Base64String -> Base64String -> Base64String)
-> (Base64String -> Base64String -> Base64String)
-> Ord Base64String
Base64String -> Base64String -> Bool
Base64String -> Base64String -> Ordering
Base64String -> Base64String -> Base64String
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Base64String -> Base64String -> Base64String
$cmin :: Base64String -> Base64String -> Base64String
max :: Base64String -> Base64String -> Base64String
$cmax :: Base64String -> Base64String -> Base64String
>= :: Base64String -> Base64String -> Bool
$c>= :: Base64String -> Base64String -> Bool
> :: Base64String -> Base64String -> Bool
$c> :: Base64String -> Base64String -> Bool
<= :: Base64String -> Base64String -> Bool
$c<= :: Base64String -> Base64String -> Bool
< :: Base64String -> Base64String -> Bool
$c< :: Base64String -> Base64String -> Bool
compare :: Base64String -> Base64String -> Ordering
$ccompare :: Base64String -> Base64String -> Ordering
$cp1Ord :: Eq Base64String
Ord, b -> Base64String -> Base64String
NonEmpty Base64String -> Base64String
Base64String -> Base64String -> Base64String
(Base64String -> Base64String -> Base64String)
-> (NonEmpty Base64String -> Base64String)
-> (forall b. Integral b => b -> Base64String -> Base64String)
-> Semigroup Base64String
forall b. Integral b => b -> Base64String -> Base64String
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Base64String -> Base64String
$cstimes :: forall b. Integral b => b -> Base64String -> Base64String
sconcat :: NonEmpty Base64String -> Base64String
$csconcat :: NonEmpty Base64String -> Base64String
<> :: Base64String -> Base64String -> Base64String
$c<> :: Base64String -> Base64String -> Base64String
Semigroup, Semigroup Base64String
Base64String
Semigroup Base64String =>
Base64String
-> (Base64String -> Base64String -> Base64String)
-> ([Base64String] -> Base64String)
-> Monoid Base64String
[Base64String] -> Base64String
Base64String -> Base64String -> Base64String
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Base64String] -> Base64String
$cmconcat :: [Base64String] -> Base64String
mappend :: Base64String -> Base64String -> Base64String
$cmappend :: Base64String -> Base64String -> Base64String
mempty :: Base64String
$cmempty :: Base64String
$cp1Monoid :: Semigroup Base64String
Monoid, Base64String -> Int
Base64String -> Ptr p -> IO ()
Base64String -> (Ptr p -> IO a) -> IO a
(Base64String -> Int)
-> (forall p a. Base64String -> (Ptr p -> IO a) -> IO a)
-> (forall p. Base64String -> Ptr p -> IO ())
-> ByteArrayAccess Base64String
forall p. Base64String -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. Base64String -> (Ptr p -> IO a) -> IO a
copyByteArrayToPtr :: Base64String -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. Base64String -> Ptr p -> IO ()
withByteArray :: Base64String -> (Ptr p -> IO a) -> IO a
$cwithByteArray :: forall p a. Base64String -> (Ptr p -> IO a) -> IO a
length :: Base64String -> Int
$clength :: Base64String -> Int
ByteArrayAccess, Eq Base64String
Ord Base64String
Monoid Base64String
ByteArrayAccess Base64String
(Eq Base64String, Ord Base64String, Monoid Base64String,
 ByteArrayAccess Base64String) =>
(forall p a. Int -> (Ptr p -> IO a) -> IO (a, Base64String))
-> ByteArray Base64String
Int -> (Ptr p -> IO a) -> IO (a, Base64String)
forall ba.
(Eq ba, Ord ba, Monoid ba, ByteArrayAccess ba) =>
(forall p a. Int -> (Ptr p -> IO a) -> IO (a, ba)) -> ByteArray ba
forall p a. Int -> (Ptr p -> IO a) -> IO (a, Base64String)
allocRet :: Int -> (Ptr p -> IO a) -> IO (a, Base64String)
$callocRet :: forall p a. Int -> (Ptr p -> IO a) -> IO (a, Base64String)
$cp4ByteArray :: ByteArrayAccess Base64String
$cp3ByteArray :: Monoid Base64String
$cp2ByteArray :: Ord Base64String
$cp1ByteArray :: Eq Base64String
ByteArray)

instance Show Base64String where
    show :: Base64String -> String
show = ("Base64String " String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> (Base64String -> String) -> Base64String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
forall a. Show a => a -> String
show (Text -> String)
-> (Base64String -> Text) -> Base64String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64String -> Text
format

instance IsString Base64String where
    fromString :: String -> Base64String
fromString = ByteString -> Base64String
base64String' (ByteString -> Base64String)
-> (String -> ByteString) -> String -> Base64String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
forall a. IsString a => String -> a
fromString
      where
        base64String' :: ByteString -> Base64String
        base64String' :: ByteString -> Base64String
base64String' = (String -> Base64String)
-> (Base64String -> Base64String)
-> Either String Base64String
-> Base64String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Base64String
forall a. HasCallStack => String -> a
error Base64String -> Base64String
forall a. a -> a
id (Either String Base64String -> Base64String)
-> (ByteString -> Either String Base64String)
-> ByteString
-> Base64String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Base64String
forall ba. ByteArray ba => ba -> Either String Base64String
base64String

instance FromJSON Base64String where
    parseJSON :: Value -> Parser Base64String
parseJSON Null = Base64String -> Parser Base64String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Base64String
forall ba. ByteArrayAccess ba => ba -> Base64String
fromBytes ("" :: ByteString))
    parseJSON v :: Value
v = String
-> (Text -> Parser Base64String) -> Value -> Parser Base64String
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText "Base64String" ((String -> Parser Base64String)
-> (Base64String -> Parser Base64String)
-> Either String Base64String
-> Parser Base64String
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser Base64String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail Base64String -> Parser Base64String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Base64String -> Parser Base64String)
-> (Text -> Either String Base64String)
-> Text
-> Parser Base64String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Base64String
forall ba. ByteArray ba => ba -> Either String Base64String
base64String (ByteString -> Either String Base64String)
-> (Text -> ByteString) -> Text -> Either String Base64String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8) Value
v

instance ToJSON Base64String where
    toJSON :: Base64String -> Value
toJSON = Text -> Value
String (Text -> Value) -> (Base64String -> Text) -> Base64String -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64String -> Text
toText

-- | Smart constructor that works with any mixed casing of characters:
--   `Base64String "AA" == Base64String "0xAa" == Base64String "0xaA" == Base64String "aa"`
base64String :: ByteArray ba => ba -> Either String Base64String
base64String :: ba -> Either String Base64String
base64String bs :: ba
bs = ByteString -> Base64String
Base64String (ByteString -> Base64String)
-> Either String ByteString -> Either String Base64String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Base -> ba -> Either String ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> Either String bout
convertFromBase Base
Base64 ba
bs

-- | Reads a raw bytes and converts to hex representation.
fromBytes :: ByteArrayAccess ba => ba -> Base64String
fromBytes :: ba -> Base64String
fromBytes = ByteString -> Base64String
Base64String (ByteString -> Base64String)
-> (ba -> ByteString) -> ba -> Base64String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ba -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert

-- | Access to the raw bytes of 'Base64String'.
toBytes :: ByteArray ba => Base64String -> ba
toBytes :: Base64String -> ba
toBytes = ByteString -> ba
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (ByteString -> ba)
-> (Base64String -> ByteString) -> Base64String -> ba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64String -> ByteString
unBase64String

-- | Access to a 'Text' representation of the 'Base64String'
toText :: Base64String -> Text
toText :: Base64String -> Text
toText = ByteString -> Text
decodeUtf8 (ByteString -> Text)
-> (Base64String -> ByteString) -> Base64String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base -> ByteString -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base64 (ByteString -> ByteString)
-> (Base64String -> ByteString) -> Base64String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64String -> ByteString
unBase64String

-- | Access to a 'Text' representation of the 'Base64String'
format :: Base64String -> Text
format :: Base64String -> Text
format = Base64String -> Text
toText