Search code examples
haskelltypesbinarybytestring

returning a list of a type from parsing a byte stream in which the length is not known until runtime


I think this is more of my lack of understanding the intricacy of Types than anything else. Trying to solve this I feel that I've been close a couple of times but not there yet.

I am trying to read from a stream using Data.Binary. I've reached a point in which the next section could have one or more of a chunk, but information isn't known until you start parsing the stream. I am having issues returning those multiple chunks.

Here is the code, and if I going about this the wrong way please let me know. But keep in mind that I need to be able to easily use the same scaffolding to write back to the stream.

Possibly Helpful Information:

  • The stream is a PE File
  • I am using lenses (fclabels)
  • The DataDirectory type is nested a few levels deep within other types.
data DataDirectory = 
  DataDirectory { _dataEntryList ::  [DataEntry] } deriving (Show, Eq, Ord)

data DataEntry = DataEntry
  { _virtAddr :: Word32            -- VirtualAddress ^ relative virtual address of the table
  , _size :: Word32                -- Size ^ size of the table in bytes
  } deriving (Show, Eq, Ord)

parseDataDir :: Word32 -> Get DataDirectory
parseDataDir n = do
  -- PE Files have a maximum of 16 sections in the DataDir
  -- most windows tools just set this to 16 by default
  -- instead of hard-coding 16 sections we will verify
  let nDirs = fromIntegral (min mAX_NUMBEROF_DIRECTORY_ENTRIES n) :: Int
  dd_dentries <- parseDataEntry nDirs

  return $ DataDirectory dd_dentries

parseDataEntry :: Int -> [Get DataEntry] -- Not exactly sure on return type here
parseDataEntry n = 
  Prelude.replicate n $ getWord32le >>= \vAddr -> getWord32le >>= \ddSize -> return $ DataEntry vAddr ddSize

I have thus far avoided grabbing the entire stream and multiplying nDirs by 8 bytes to get the length and parse. This certainly would work for this instance but possibly not downrange in other spots.


Solution

  • Use Hoogle to search for the type you want.