packages feed

octane-0.10.0: library/Octane/Type/Primitive/Stream.hs

{-# LANGUAGE DeriveGeneric #-}

module Octane.Type.Primitive.Stream (Stream(..)) where

import qualified Control.DeepSeq as DeepSeq
import qualified Data.Aeson as Aeson
import qualified Data.Binary as Binary
import qualified Data.Binary.Get as Binary
import qualified Data.Binary.Put as Binary
import qualified Data.ByteString as BS
import Data.Function ((&))
import qualified GHC.Generics as Generics
import qualified Octane.Type.Primitive.Int32 as Int32
import qualified Octane.Utility as Utility

-- | A length-prefixed stream of bits. The length is given in bytes. Each byte
-- is reversed such that 0b01234567 is actually 0b76543210.
newtype Stream = Stream
    { unpackStream :: BS.ByteString
    } deriving (Eq,Generics.Generic,Show)

instance Binary.Binary Stream where
    get = do
        Int32.Int32 size <- Binary.get
        content <- size & fromIntegral & Binary.getByteString
        content & BS.map Utility.reverseBits & Stream & return
    put stream = do
        let content = unpackStream stream
        content & BS.length & fromIntegral & Int32.Int32 & Binary.put
        content & BS.map Utility.reverseBits & Binary.putByteString

instance DeepSeq.NFData Stream

instance Aeson.ToJSON Stream where
    toJSON stream =
        let size = stream & unpackStream & BS.length
            bytes =
                if size == 1
                    then "byte"
                    else "bytes"
        in Aeson.toJSON (unwords ["Stream:", show size, bytes, "..."])