never executed always true always false
    1 module GHC.Iface.Ext.Fields
    2    ( ExtensibleFields (..)
    3    , FieldName
    4    , emptyExtensibleFields
    5    -- * Reading
    6    , readField
    7    , readFieldWith
    8    -- * Writing
    9    , writeField
   10    , writeFieldWith
   11    -- * Deletion
   12    , deleteField
   13    )
   14 where
   15 
   16 import GHC.Prelude
   17 import GHC.Utils.Binary
   18 
   19 import Control.Monad
   20 import Data.Map         ( Map )
   21 import qualified Data.Map as Map
   22 import Control.DeepSeq
   23 
   24 type FieldName = String
   25 
   26 newtype ExtensibleFields = ExtensibleFields { getExtensibleFields :: (Map FieldName BinData) }
   27 
   28 instance Binary ExtensibleFields where
   29   put_ bh (ExtensibleFields fs) = do
   30     put_ bh (Map.size fs :: Int)
   31 
   32     -- Put the names of each field, and reserve a space
   33     -- for a payload pointer after each name:
   34     header_entries <- forM (Map.toList fs) $ \(name, dat) -> do
   35       put_ bh name
   36       field_p_p <- tellBin bh
   37       put_ bh field_p_p
   38       return (field_p_p, dat)
   39 
   40     -- Now put the payloads and use the reserved space
   41     -- to point to the start of each payload:
   42     forM_ header_entries $ \(field_p_p, dat) -> do
   43       field_p <- tellBin bh
   44       putAt bh field_p_p field_p
   45       seekBin bh field_p
   46       put_ bh dat
   47 
   48   get bh = do
   49     n <- get bh :: IO Int
   50 
   51     -- Get the names and field pointers:
   52     header_entries <- replicateM n $
   53       (,) <$> get bh <*> get bh
   54 
   55     -- Seek to and get each field's payload:
   56     fields <- forM header_entries $ \(name, field_p) -> do
   57       seekBin bh field_p
   58       dat <- get bh
   59       return (name, dat)
   60 
   61     return . ExtensibleFields . Map.fromList $ fields
   62 
   63 instance NFData ExtensibleFields where
   64   rnf (ExtensibleFields fs) = rnf fs
   65 
   66 emptyExtensibleFields :: ExtensibleFields
   67 emptyExtensibleFields = ExtensibleFields Map.empty
   68 
   69 --------------------------------------------------------------------------------
   70 -- | Reading
   71 
   72 readField :: Binary a => FieldName -> ExtensibleFields -> IO (Maybe a)
   73 readField name = readFieldWith name get
   74 
   75 readFieldWith :: FieldName -> (BinHandle -> IO a) -> ExtensibleFields -> IO (Maybe a)
   76 readFieldWith name read fields = sequence $ ((read =<<) . dataHandle) <$>
   77   Map.lookup name (getExtensibleFields fields)
   78 
   79 --------------------------------------------------------------------------------
   80 -- | Writing
   81 
   82 writeField :: Binary a => FieldName -> a -> ExtensibleFields -> IO ExtensibleFields
   83 writeField name x = writeFieldWith name (`put_` x)
   84 
   85 writeFieldWith :: FieldName -> (BinHandle -> IO ()) -> ExtensibleFields -> IO ExtensibleFields
   86 writeFieldWith name write fields = do
   87   bh <- openBinMem (1024 * 1024)
   88   write bh
   89   --
   90   bd <- handleData bh
   91   return $ ExtensibleFields (Map.insert name bd $ getExtensibleFields fields)
   92 
   93 deleteField :: FieldName -> ExtensibleFields -> ExtensibleFields
   94 deleteField name (ExtensibleFields fs) = ExtensibleFields $ Map.delete name fs