{-| Description : Utilities for packing stuff Maintainer : srk |-} module System.Nix.Util where import Control.Monad import Data.Binary.Get import Data.Binary.Put import qualified Data.ByteString.Lazy as LBS putInt :: Integral a => a -> Put putInt = putWord64le . fromIntegral getInt :: Integral a => Get a getInt = fromIntegral <$> getWord64le -- length prefixed string packing with padding to 8 bytes putByteStringLen :: LBS.ByteString -> Put putByteStringLen x = do putInt $ fromIntegral $ len putLazyByteString x when (len `mod` 8 /= 0) $ pad $ fromIntegral $ 8 - (len `mod` 8) where len = LBS.length x pad x = forM_ (take x $ cycle [0]) putWord8 putByteStrings :: Foldable t => t LBS.ByteString -> Put putByteStrings xs = do putInt $ fromIntegral $ length xs mapM_ putByteStringLen xs getByteStringLen :: Get LBS.ByteString getByteStringLen = do len <- getInt st <- getLazyByteString len when (len `mod` 8 /= 0) $ do pads <- unpad $ fromIntegral $ 8 - (len `mod` 8) unless (all (==0) pads) $ fail $ "No zeroes" ++ show (st, len, pads) return st where unpad x = sequence $ replicate x getWord8 getByteStrings :: Get [LBS.ByteString] getByteStrings = do count <- getInt res <- sequence $ replicate count getByteStringLen return res