-- Copyright 2013 Thomas Szczarkowski

module Bytes where

import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as Char8
import qualified Data.ByteString.Base64 as ByteString.Base64
import Data.Word
import Text.Printf

-- boilerplate
-- trivial conversions of binary string types:
--   * Lists of bytes ([Word8]), the default
--   * Packed vectors of bytes (ByteString), for OpenSSL FFI
--   * Unicode strings, chars truncated to 8 bits ([Char8])
--   * hex-encoded strings
--   * base64-encoded strings


class Bytes t where
  encode :: [Word8] -> t  
  decode :: t -> [Word8]
  transcode :: Bytes t' => t -> t'
  transcode = encode . decode
  

data Base64 = Base64 String deriving Eq
data Hex = Hex String deriving Eq

instance Show Base64 where
  show (Base64 s) = s

instance Show Hex where
  show (Hex s) = s


instance Bytes [Word8] where  
  encode = id
  decode = id
  

instance Bytes Char8.ByteString where  
  encode = ByteString.pack
  decode = ByteString.unpack
  

instance Bytes Base64 where  
  encode s = Base64 $ show $ ByteString.Base64.encode $ encode s
  decode (Base64 s) = decode $ ByteString.Base64.decodeLenient $ transcode s
  

instance Bytes Hex where
  encode = Hex . concat . (map (printf "%02x"))
  decode (Hex (x:y:rest)) = (read ("0x" ++ [x,y])) : (decode $ Hex rest)
  decode _ = []


instance Bytes [Char] where
  encode = Char8.unpack . ByteString.pack    
  decode = ByteString.unpack . Char8.pack

