module Serializable (Serializable, encode, decode) where

import Data.Binary.Get (getInt64le, getLazyByteString, getWord32le, runGet)
import Data.Binary.Put (putInt64le, putLazyByteString, putWord32le, runPut)
import qualified Data.ByteString.Lazy as B
import Entry (Entry (..))

class Serializable a where
  encode :: a -> B.ByteString
  decode :: B.ByteString -> a

instance Serializable Entry where
  encode :: Entry -> ByteString
encode (Entry Checksum
checksum Timestamp
timestamp Timestamp
ksize Timestamp
vsize ByteString
key ByteString
value) =
    Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Checksum -> Put
putWord32le Checksum
checksum Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> Timestamp -> Put
putInt64le Timestamp
timestamp Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> Timestamp -> Put
putInt64le Timestamp
ksize Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> Timestamp -> Put
putInt64le Timestamp
vsize Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> ByteString -> Put
putLazyByteString ByteString
key Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> ByteString -> Put
putLazyByteString ByteString
value
  decode :: ByteString -> Entry
decode ByteString
content = Checksum
-> Timestamp
-> Timestamp
-> Timestamp
-> ByteString
-> ByteString
-> Entry
Entry Checksum
checksum Timestamp
timestamp Timestamp
ksize Timestamp
vsize ByteString
key ByteString
value
    where
      value :: ByteString
value = Get ByteString -> ByteString -> ByteString
forall a. Get a -> ByteString -> a
runGet (Timestamp -> Get ByteString
getLazyByteString Timestamp
vsize) (Timestamp -> ByteString -> ByteString
B.drop (Timestamp
4 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
ksize) ByteString
content)
      key :: ByteString
key = Get ByteString -> ByteString -> ByteString
forall a. Get a -> ByteString -> a
runGet (Timestamp -> Get ByteString
getLazyByteString Timestamp
ksize) (Timestamp -> ByteString -> ByteString
B.drop (Timestamp
4 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8) ByteString
content)
      vsize :: Timestamp
vsize = Get Timestamp -> ByteString -> Timestamp
forall a. Get a -> ByteString -> a
runGet Get Timestamp
getInt64le (Timestamp -> ByteString -> ByteString
B.drop (Timestamp
4 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8) ByteString
content)
      ksize :: Timestamp
ksize = Get Timestamp -> ByteString -> Timestamp
forall a. Get a -> ByteString -> a
runGet Get Timestamp
getInt64le (Timestamp -> ByteString -> ByteString
B.drop (Timestamp
4 Timestamp -> Timestamp -> Timestamp
forall a. Num a => a -> a -> a
+ Timestamp
8) ByteString
content)
      timestamp :: Timestamp
timestamp = Get Timestamp -> ByteString -> Timestamp
forall a. Get a -> ByteString -> a
runGet Get Timestamp
getInt64le (Timestamp -> ByteString -> ByteString
B.drop Timestamp
4 ByteString
content)
      checksum :: Checksum
checksum = Get Checksum -> ByteString -> Checksum
forall a. Get a -> ByteString -> a
runGet Get Checksum
getWord32le ByteString
content