{-# LANGUAGE CPP #-} {-# 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 #if MIN_VERSION_bytestring(0,10,2) import qualified Data.ByteString.Builder as BB #elif MIN_VERSION_bytestring(0,10,0) import qualified Data.ByteString.Lazy.Builder as BB #endif import qualified Data.ByteString.Lazy as BS.L #if MIN_VERSION_bytestring(0,10,4) import qualified Data.ByteString.Short as SBS #endif 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 txt | BS.null rest = Right $! b | otherwise = Left ("invalid base16 encoding near offset " ++ show (2 * BS.length b)) where (b,rest) = B16.decode txt decodeBsL2BsL :: BS.L.ByteString -> Either String BS.L.ByteString decodeBsL2BsL txt | BS.L.null rest = Right $! b | otherwise = Left ("invalid base16 encoding near offset " ++ show (2 * BS.L.length b)) where (b,rest) = B16.L.decode txt 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 #if MIN_VERSION_bytestring(0,10,0) instance Encode BS.L.ByteString BB.Builder where encode = BB.lazyByteString . encode #endif #if MIN_VERSION_bytestring(0,10,4) instance Encode BS.L.ByteString SBS.ShortByteString where encode = SBS.toShort . encode #endif 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 #if MIN_VERSION_bytestring(0,10,0) instance Encode BS.ByteString BB.Builder where encode = BB.byteString . encode #endif #if MIN_VERSION_bytestring(0,10,4) instance Encode BS.ByteString SBS.ShortByteString where encode = SBS.toShort . encode #endif 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 -> * #if MIN_VERSION_bytestring(0,10,4) 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 #endif ---- BB -> * #if MIN_VERSION_bytestring(0,10,4) instance Encode BB.Builder SBS.ShortByteString where encode = encode . BB.toLazyByteString #endif #if MIN_VERSION_bytestring(0,10,0) 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 #endif ------------------------------------------------------------------------------ -- PRIMITIVE instance Decode BS.ByteString BS.ByteString where decode = decodeBs2Bs instance Decode BS.ByteString BS.L.ByteString where decode = fmap bsFromStrict . decode #if MIN_VERSION_bytestring(0,10,4) instance Decode BS.ByteString SBS.ShortByteString where decode = fmap SBS.toShort . decode #endif #if MIN_VERSION_bytestring(0,10,0) instance Decode BS.ByteString BB.Builder where decode = fmap BB.byteString . decode #endif ---- -- PRIMITIVE instance Decode BS.L.ByteString BS.L.ByteString where decode = decodeBsL2BsL instance Decode BS.L.ByteString BS.ByteString where decode = fmap bsToStrict . decode #if MIN_VERSION_bytestring(0,10,4) instance Decode BS.L.ByteString SBS.ShortByteString where decode = fmap SBS.toShort . decode #endif #if MIN_VERSION_bytestring(0,10,0) instance Decode BS.L.ByteString BB.Builder where decode = fmap BB.byteString . decode #endif ---- #if MIN_VERSION_bytestring(0,10,4) 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 #endif ---- #if MIN_VERSION_bytestring(0,10,4) instance Decode BB.Builder SBS.ShortByteString where decode = decode . BB.toLazyByteString #endif #if MIN_VERSION_bytestring(0,10,0) 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 #endif ---- instance Decode T.Text BS.ByteString where decode = decode . T.encodeUtf8 instance Decode T.Text BS.L.ByteString where decode = decode . T.encodeUtf8 #if MIN_VERSION_bytestring(0,10,4) instance Decode T.Text SBS.ShortByteString where decode = decode . T.encodeUtf8 #endif #if MIN_VERSION_bytestring(0,10,0) instance Decode T.Text BB.Builder where decode = decode . T.encodeUtf8 #endif ---- 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 #if MIN_VERSION_bytestring(0,10,4) instance Decode T.L.Text SBS.ShortByteString where decode = decode . T.L.encodeUtf8 #endif #if MIN_VERSION_bytestring(0,10,0) instance Decode T.L.Text BB.Builder where decode = decode . T.L.encodeUtf8 #endif ---- instance Decode TB.Builder BS.ByteString where decode = decode . TB.toLazyText instance Decode TB.Builder BS.L.ByteString where decode = decode . TB.toLazyText #if MIN_VERSION_bytestring(0,10,4) instance Decode TB.Builder SBS.ShortByteString where decode = decode . TB.toLazyText #endif #if MIN_VERSION_bytestring(0,10,0) instance Decode TB.Builder BB.Builder where decode = decode . TB.toLazyText #endif