module Raaz.Core.Encode.Internal
( Encodable(..), Format(..)
, encode, decode, unsafeDecode
) where
import Data.Maybe
import Data.ByteString (ByteString)
import Data.ByteString.Internal (unsafeCreate)
import Data.String
import Data.Word
import Foreign.Ptr
import Foreign.Storable
import Prelude hiding (length)
import System.IO.Unsafe (unsafePerformIO)
import Raaz.Core.Types.Endian
import Raaz.Core.Types.Pointer
import Raaz.Core.Util.ByteString(length, withByteString)
class Encodable a where
toByteString :: a -> ByteString
fromByteString :: ByteString -> Maybe a
unsafeFromByteString :: ByteString -> a
default toByteString :: EndianStore a => a -> ByteString
toByteString w = unsafeCreate (sizeOf w) putit
where putit ptr = store (castPtr ptr) w
default fromByteString :: EndianStore a => ByteString -> Maybe a
fromByteString bs | byteSize proxy == length bs = Just w
| otherwise = Nothing
where w = unsafePerformIO $ withByteString bs (load . castPtr)
proxy = undefined `asTypeOf` w
unsafeFromByteString = fromMaybe (error "fromByteString error") . fromByteString
instance Encodable (LE Word32)
instance Encodable (LE Word64)
instance Encodable (BE Word32)
instance Encodable (BE Word64)
instance Encodable ByteString where
toByteString = id
fromByteString = Just . id
unsafeFromByteString = id
instance Encodable a => Encodable (BITS a) where
toByteString (BITS a) = toByteString a
fromByteString = fmap BITS . fromByteString
unsafeFromByteString = BITS . unsafeFromByteString
instance Encodable a => Encodable (BYTES a) where
toByteString (BYTES a) = toByteString a
fromByteString = fmap BYTES . fromByteString
unsafeFromByteString = BYTES . unsafeFromByteString
class (IsString fmt, Show fmt, Encodable fmt) => Format fmt where
encodeByteString :: ByteString -> fmt
decodeFormat :: fmt -> ByteString
instance Format ByteString where
encodeByteString = id
decodeFormat = id
encode :: (Encodable a, Format fmt) => a -> fmt
encode = encodeByteString . toByteString
decode :: (Format fmt, Encodable a) => fmt -> Maybe a
decode = fromByteString . decodeFormat
unsafeDecode :: (Format fmt, Encodable a) => fmt -> a
unsafeDecode = unsafeFromByteString . decodeFormat