    module Hackage.Security.Util.Base64 (
        Base64 -- opaque
      , fromByteString
      , toByteString
      ) where

    import Prelude
    import Data.ByteString (ByteString)
    import qualified Data.ByteString.Char8  as C8  -- only called on B64-enc strings
    import qualified Data.ByteString.Base64 as B64

    import Hackage.Security.Util.JSON

    -- | Simple wrapper around bytestring with ToJSON and FromJSON instances that
    -- use base64 encoding.
    newtype Base64 = Base64 ByteString

    fromByteString :: ByteString -> Base64
    fromByteString :: ByteString -> Base64
    fromByteString = ByteString -> Base64
    Base64

    toByteString :: Base64 -> ByteString
    toByteString :: Base64 -> ByteString
    toByteString (Base64 ByteString
    bs) = ByteString
    bs

    instance Monad m => ToJSON m Base64 where
      toJSON :: Base64 -> m JSValue
    toJSON (Base64 ByteString
    bs) = [Char] -> m JSValue
    forall (m :: * -> *) a. ToJSON m a => a -> m JSValue
    toJSON (ByteString -> [Char]
    C8.unpack (ByteString -> ByteString
    B64.encode ByteString
    bs))

    instance ReportSchemaErrors m => FromJSON m Base64 where
      fromJSON :: JSValue -> m Base64
    fromJSON JSValue
    val = do
        str <- JSValue -> m [Char]
    forall (m :: * -> *) a. FromJSON m a => JSValue -> m a
    fromJSON JSValue
    val
        case B64.decode (C8.pack str) of
          Left [Char]
    _err -> [Char] -> Maybe [Char] -> m Base64
    forall a. [Char] -> Maybe [Char] -> m a
    forall (m :: * -> *) a.
    ReportSchemaErrors m =>
    [Char] -> Maybe [Char] -> m a
    expected [Char]
    "base-64 encoded string" Maybe [Char]
    forall a. Maybe a
    Nothing
          Right ByteString
    bs  -> Base64 -> m Base64
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Base64 -> m Base64) -> Base64 -> m Base64
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Base64
    Base64 ByteString
    bs