{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# OPTIONS -Wall #-} ---------------------------------------------------------------------- -- | -- Module : Blaze.ByteString.Builder.ZoomCache -- Copyright : Conrad Parker -- License : BSD3-style (see LICENSE) -- -- Maintainer : Conrad Parker -- Stability : unstable -- Portability : unknown -- -- Blaze-builder utility functions for writing ZoomCache files. ---------------------------------------------------------------------- module Blaze.ByteString.Builder.ZoomCache ( -- * Creating builders for ZoomCache types fromSampleOffset -- * Creating builders from numeric types used by ZoomCache , fromFloat , fromDouble , fromIntegral32be , fromIntegerVLC , fromRational64 ) where import Blaze.ByteString.Builder import Data.Bits import Data.Monoid import Data.Ratio import Data.Word import Unsafe.Coerce (unsafeCoerce) import Data.ZoomCache.Common ---------------------------------------------------------------------- -- Creating builders for ZoomCache types. -- | Serialize a 'TimeStamp' in 64bit big endian format. fromSampleOffset :: SampleOffset -> Builder fromSampleOffset = fromInt64be . fromIntegral . unSO {-# INLINE fromSampleOffset #-} ---------------------------------------------------------------------- -- Creating builders from numeric types used by ZoomCache. -- | Serialize a 'Float' in big-endian IEEE 754-2008 binary32 format -- (IEEE 754-1985 single format). fromFloat :: Float -> Builder fromFloat = fromWord32be . toWord32 where toWord32 :: Float -> Word32 toWord32 = unsafeCoerce {-# INLINE fromFloat #-} -- | Serialize a 'Double' in big-endian IEEE 754-2008 binary64 format -- (IEEE 754-1985 double format). fromDouble :: Double -> Builder fromDouble = fromWord64be . toWord64 where toWord64 :: Double -> Word64 toWord64 = unsafeCoerce {-# INLINE fromDouble #-} -- | Serialize an 'Integral' in 32bit big endian format. fromIntegral32be :: forall a . (Integral a) => a -> Builder fromIntegral32be = fromInt32be . fromIntegral {-# SPECIALIZE INLINE fromIntegral32be :: Int -> Builder #-} {-# SPECIALIZE INLINE fromIntegral32be :: Integer -> Builder #-} -- | Serialize an 'Integer' in variable-length-coding format -- For details of the variable-length coding format, see -- "Data.ZoomCache.Numeric.Int". fromIntegerVLC :: Integer -> Builder fromIntegerVLC x0 = enc x1 `mappend` buildVLC xHi where x1 = (xLo `shiftL` 1) .|. sign0 sign0 | x0 < 0 = 1 | otherwise = 0 (xHi, xLo) = bCont 6 (abs x0) -- Split a bitstring of length len into a tuple of -- the top (len-n) bits and (the lower n bits with the -- extension bit set if any of the top (len-n) bits are -- non-zero). We assume n < 8. bCont :: Bits a => Int -> a -> (a, a) bCont n v | hi == 0 = (hi, lo) | otherwise = (hi, lo .|. (2^n)) where -- Split a bitstring of length len into a tuple of -- the top (len-n) bits and the lower n bits. (hi, lo) = (v `shiftR` n, v .&. (2^n -1)) -- Build a variable-length-coded sequence of bytes corresponding -- to the contents of x, 7 bits at a time. buildVLC x | x == 0 = mempty | otherwise = enc lo `mappend` buildVLC hi where (hi, lo) = bCont 7 x enc :: Integer -> Builder enc = fromWord8 . fromIntegral -- | Serialize a 'Rational' as a sequence of two 64bit big endian format -- integers. fromRational64 :: Rational -> Builder fromRational64 r = mconcat [ fromInt64be . fromIntegral . numerator $ r , fromInt64be . fromIntegral . denominator $ r ] {-# INLINE fromRational64 #-}