{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Haskus.Binary.Serialize
( Serializable (..)
, Size (..)
)
where
import Haskus.Binary.Serialize.Put
import Haskus.Binary.Serialize.Size
import Haskus.Binary.Serialize.Get
import Haskus.Number.Word
import Haskus.Number.Int
import Haskus.Binary.Endianness
import Haskus.Utils.Types
data Size
= Exactly Nat
| Dynamic
class Serializable a where
type SizeOf a :: Size
type Endian a :: Bool
sizeOf :: a -> Word
sizeOf a = runGetSize (put LittleEndian a)
put :: PutMonad m => Endianness -> a -> m ()
get :: GetMonad m => Endianness -> m a
instance Serializable Word8 where
type SizeOf Word8 = 'Exactly 1
type Endian Word8 = 'False
sizeOf _ = 1
put _ x = putWord8 x
get _ = getWord8
instance Serializable Word16 where
type SizeOf Word16 = 'Exactly 2
type Endian Word16 = 'True
sizeOf _ = 2
put LittleEndian x = putWord16LE x
put BigEndian x = putWord16BE x
get LittleEndian = getWord16LE
get BigEndian = getWord16BE
instance Serializable Word32 where
type SizeOf Word32 = 'Exactly 4
type Endian Word32 = 'True
sizeOf _ = 4
put LittleEndian x = putWord32LE x
put BigEndian x = putWord32BE x
get LittleEndian = getWord32LE
get BigEndian = getWord32BE
instance Serializable Word64 where
type SizeOf Word64 = 'Exactly 8
type Endian Word64 = 'True
sizeOf _ = 8
put LittleEndian x = putWord64LE x
put BigEndian x = putWord64BE x
get LittleEndian = getWord64LE
get BigEndian = getWord64BE
instance Serializable Int8 where
type SizeOf Int8 = 'Exactly 1
type Endian Int8 = 'False
sizeOf _ = 1
put _ x = putWord8 (fromIntegral x)
get _ = fromIntegral <$> getWord8
instance Serializable Int16 where
type SizeOf Int16 = 'Exactly 2
type Endian Int16 = 'True
sizeOf _ = 2
put LittleEndian x = putWord16LE (fromIntegral x)
put BigEndian x = putWord16BE (fromIntegral x)
get LittleEndian = fromIntegral <$> getWord16LE
get BigEndian = fromIntegral <$> getWord16BE
instance Serializable Int32 where
type SizeOf Int32 = 'Exactly 4
type Endian Int32 = 'True
sizeOf _ = 4
put LittleEndian x = putWord32LE (fromIntegral x)
put BigEndian x = putWord32BE (fromIntegral x)
get LittleEndian = fromIntegral <$> getWord32LE
get BigEndian = fromIntegral <$> getWord32BE
instance Serializable Int64 where
type SizeOf Int64 = 'Exactly 8
type Endian Int64 = 'True
sizeOf _ = 8
put LittleEndian x = putWord64LE (fromIntegral x)
put BigEndian x = putWord64BE (fromIntegral x)
get LittleEndian = fromIntegral <$> getWord64LE
get BigEndian = fromIntegral <$> getWord64BE
instance Serializable a => Serializable (AsBigEndian a) where
type SizeOf (AsBigEndian a) = SizeOf a
type Endian (AsBigEndian a) = 'False
sizeOf (AsBigEndian b) = sizeOf b
put _ (AsBigEndian x) = put BigEndian x
get _ = AsBigEndian <$> get BigEndian
instance Serializable a => Serializable (AsLittleEndian a) where
type SizeOf (AsLittleEndian a) = SizeOf a
type Endian (AsLittleEndian a) = 'False
sizeOf (AsLittleEndian b) = sizeOf b
put _ (AsLittleEndian x) = put LittleEndian x
get _ = AsLittleEndian <$> get LittleEndian