{-# 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 -- | A stream of bits. 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