packages feed

base-encoding-0.3.0.0: src/Codec/Base16.hs

{-# LANGUAGE MultiParamTypeClasses #-}

-- | This module provides access to the \"base16\" binary-to-text encoding as defined by [RFC 4648](https://tools.ietf.org/html/rfc4648).
--
-- This module is intended to be imported @qualified@, e.g.
--
-- > import qualified Codec.Base16 as B16
--
-- If you want to explictly specify which 'Encode' and 'Decode' typeclass instance is used, you can use plain Haskell2010 type-signature annotations, e.g.
--
-- >>> (B16.encode :: ByteString -> Text) "\202\254"
-- "cafe"
--
-- >>> (B16.decode :: Text -> Either String ShortByteString) "CaFe"
-- Right "\202\254"
--
-- Alternatively, starting with GHC 8.0.1, you can also use the [TypeApplications language extension](https://downloads.haskell.org/~ghc/8.4.1/docs/html/users_guide/glasgow_exts.html#ghc-flag--XTypeApplications):
--
-- >>> B16.encode @ShortByteString @Text "\xFF\239\0"
-- "ffef00"
--
-- >>> B16.decode @Text @ShortByteString ""
-- Right ""
--
-- @since 0.1.0.0
module Codec.Base16
    ( Encode(encode)
    , Decode(decode)
    ) where

import qualified Data.ByteString.Base16       as B16
import qualified Data.ByteString.Base16.Lazy  as B16.L

import qualified Data.ByteString              as BS
import qualified Data.ByteString.Builder      as BB
import qualified Data.ByteString.Lazy         as BS.L
import qualified Data.ByteString.Short        as SBS

import qualified Data.Text                    as T (Text)
import qualified Data.Text.Encoding           as T (decodeLatin1, encodeUtf8)
import qualified Data.Text.Lazy               as T.L (Text, fromStrict)
import qualified Data.Text.Lazy.Builder       as TB (Builder, fromLazyText,
                                                     fromText, toLazyText)
import qualified Data.Text.Lazy.Encoding      as T.L (decodeLatin1, encodeUtf8)

import           Internal

-- primitives

decodeBs2Bs :: BS.ByteString -> Either String BS.ByteString
decodeBs2Bs = B16.decode

decodeBsL2BsL :: BS.L.ByteString -> Either String BS.L.ByteString
decodeBsL2BsL = B16.L.decode

encodeBs2Bs :: BS.ByteString -> BS.ByteString
encodeBs2Bs = B16.encode

encodeBsL2BsL :: BS.L.ByteString -> BS.L.ByteString
encodeBsL2BsL = B16.L.encode

----------------------------------------------------------------------------
-- exposed API

-- | Typeclass representing types for which a binary-to-text @base16@ encoding is defined
class Encode bin txt where
  -- | Encode binary data using @base16@ text encoding
  encode :: bin -> txt

-- | Typeclass representing types for which a text-to-binary @base16@ decoding is defined
class Decode txt bin where
  -- | Decode binary data encoded textually as @base16@
  decode :: txt -> Either String bin

----------------------------------------------------------------------------
-- instance matrix

---- lazy BS -> *

-- PRIMITIVE
instance Encode BS.L.ByteString BS.L.ByteString where
  encode = encodeBsL2BsL

instance Encode BS.L.ByteString BS.ByteString where
  encode = bsToStrict . encode

instance Encode BS.L.ByteString BB.Builder where
  encode = BB.lazyByteString . encode

instance Encode BS.L.ByteString SBS.ShortByteString where
  encode = SBS.toShort . encode

instance Encode BS.L.ByteString T.Text where
  encode = T.decodeLatin1 . encode

instance Encode BS.L.ByteString T.L.Text where
  encode = T.L.decodeLatin1 . encode

instance Encode BS.L.ByteString TB.Builder where
  encode = TB.fromLazyText . encode

---- strict BS  -> *

-- PRIMITIVE
instance Encode BS.ByteString BS.ByteString where
  encode = encodeBs2Bs

instance Encode BS.ByteString BS.L.ByteString where
  encode = bsFromStrict . encode

instance Encode BS.ByteString BB.Builder where
  encode = BB.byteString . encode

instance Encode BS.ByteString SBS.ShortByteString where
  encode = SBS.toShort . encode

instance Encode BS.ByteString T.Text where
  encode = T.decodeLatin1 . encode

instance Encode BS.ByteString T.L.Text where
  encode = T.L.fromStrict . T.decodeLatin1 . encode

instance Encode BS.ByteString TB.Builder where
  encode = TB.fromText . encode

---- short BS  -> *

instance Encode SBS.ShortByteString SBS.ShortByteString where
  encode = SBS.toShort . encode . SBS.fromShort

instance Encode SBS.ShortByteString BS.ByteString where
  encode = encode . SBS.fromShort

instance Encode SBS.ShortByteString BS.L.ByteString where
  encode = encode . SBS.fromShort

instance Encode SBS.ShortByteString BB.Builder where
  encode = encode . SBS.fromShort

instance Encode SBS.ShortByteString T.Text where
  encode = T.decodeLatin1 . encode

instance Encode SBS.ShortByteString T.L.Text where
  encode = T.L.fromStrict . T.decodeLatin1 . encode

instance Encode SBS.ShortByteString TB.Builder where
  encode = TB.fromText . encode

---- BB  -> *

instance Encode BB.Builder SBS.ShortByteString where
  encode = encode . BB.toLazyByteString

instance Encode BB.Builder BB.Builder where
  encode = encode . BB.toLazyByteString

instance Encode BB.Builder BS.ByteString where
  encode = encode . BB.toLazyByteString

instance Encode BB.Builder BS.L.ByteString where
  encode = encode . BB.toLazyByteString

instance Encode BB.Builder T.Text where
  encode = T.decodeLatin1 . encode

instance Encode BB.Builder T.L.Text where
  encode = T.L.decodeLatin1 . encode

instance Encode BB.Builder TB.Builder where
  encode = TB.fromLazyText . encode

------------------------------------------------------------------------------

-- PRIMITIVE
instance Decode BS.ByteString BS.ByteString where
  decode = decodeBs2Bs

instance Decode BS.ByteString BS.L.ByteString where
  decode = fmap bsFromStrict . decode

instance Decode BS.ByteString SBS.ShortByteString where
  decode = fmap SBS.toShort . decode

instance Decode BS.ByteString BB.Builder where
  decode = fmap BB.byteString . decode

----

-- PRIMITIVE
instance Decode BS.L.ByteString BS.L.ByteString where
  decode = decodeBsL2BsL

instance Decode BS.L.ByteString BS.ByteString where
  decode = fmap bsToStrict . decode

instance Decode BS.L.ByteString SBS.ShortByteString where
  decode = fmap SBS.toShort . decode

instance Decode BS.L.ByteString BB.Builder where
  decode = fmap BB.byteString . decode

----

instance Decode SBS.ShortByteString SBS.ShortByteString where
  decode = fmap SBS.toShort . decode . SBS.fromShort

instance Decode SBS.ShortByteString BS.ByteString where
  decode = decode . SBS.fromShort

instance Decode SBS.ShortByteString BS.L.ByteString where
  decode = decode . SBS.fromShort

instance Decode SBS.ShortByteString BB.Builder where
  decode = decode . SBS.fromShort

----

instance Decode BB.Builder SBS.ShortByteString where
  decode = decode . BB.toLazyByteString

instance Decode BB.Builder BS.L.ByteString where
  decode = decode . BB.toLazyByteString

instance Decode BB.Builder BS.ByteString where
  decode = decode . BB.toLazyByteString

instance Decode BB.Builder BB.Builder where
  decode = decode . BB.toLazyByteString

----

instance Decode T.Text BS.ByteString where
  decode = decode . T.encodeUtf8

instance Decode T.Text BS.L.ByteString where
  decode = decode . T.encodeUtf8

instance Decode T.Text SBS.ShortByteString where
  decode = decode . T.encodeUtf8

instance Decode T.Text BB.Builder where
  decode = decode . T.encodeUtf8

----

instance Decode T.L.Text BS.ByteString where
  decode = decode . T.L.encodeUtf8

instance Decode T.L.Text BS.L.ByteString where
  decode = decode . T.L.encodeUtf8

instance Decode T.L.Text SBS.ShortByteString where
  decode = decode . T.L.encodeUtf8

instance Decode T.L.Text BB.Builder where
  decode = decode . T.L.encodeUtf8

----

instance Decode TB.Builder BS.ByteString where
  decode = decode . TB.toLazyText

instance Decode TB.Builder BS.L.ByteString where
  decode = decode . TB.toLazyText

instance Decode TB.Builder SBS.ShortByteString where
  decode = decode . TB.toLazyText

instance Decode TB.Builder BB.Builder where
  decode = decode . TB.toLazyText