{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Octane.Type.Stream
( Stream(..)
) where
import Data.Function ((&))
import qualified Control.DeepSeq as DeepSeq
import qualified Data.Binary as Binary
import qualified Data.Binary.Get as Binary
import qualified Data.Binary.Put as Binary
import qualified Data.ByteString.Lazy as LazyBytes
import qualified Data.Default.Class as Default
import qualified Data.OverloadedRecords.TH as OverloadedRecords
import qualified GHC.Generics as Generics
import qualified Octane.Type.Word32 as Word32
import qualified Octane.Utility.Endian as Endian
import qualified Text.Printf as Printf
newtype Stream = Stream
{ streamUnpack :: LazyBytes.ByteString
} deriving (Eq, Generics.Generic)
$(OverloadedRecords.overloadedRecord Default.def ''Stream)
-- | Prefixed by a length in bytes. Each byte is reversed such that
-- @0b01234567@ is actually @0b76543210@.
instance Binary.Binary Stream where
get = do
size <- Binary.get
content <- size & Word32.fromWord32 & Binary.getLazyByteString
content & Endian.reverseBitsInLazyBytes & Stream & pure
put stream = do
let content = #unpack stream
content & LazyBytes.length & Word32.toWord32 & Binary.put
content & Endian.reverseBitsInLazyBytes & Binary.putLazyByteString
instance DeepSeq.NFData Stream
-- | Doesn't show the actual bytes to avoid dumping tons of text.
instance Show Stream where
show stream = do
let size = stream & #unpack & LazyBytes.length
let s =
if size == 1
then ""
else "s"
Printf.printf "Stream {unpack = \"%d byte%s\"}" size s