Skip to content

Instantly share code, notes, and snippets.

@redrabbit
Last active December 7, 2017 13:34
Show Gist options
  • Save redrabbit/eb4b462ba2e44100471bc26546b3f71c to your computer and use it in GitHub Desktop.
Save redrabbit/eb4b462ba2e44100471bc26546b3f71c to your computer and use it in GitHub Desktop.
readCopyInstruction :: (Integral a) => Word8 -> Get (a, a)
readCopyInstruction opcode = do
-- off -> offset in the source buffer where the copy will start
-- this will read the correct subsequent bytes and shift them based on
-- the set bit
offset <- foldM readIfBitSet 0 $ zip [0x01, 0x02, 0x04, 0x08] [0,8..]
-- bytes to copy
len' <- foldM readIfBitSet 0 $ zip [0x10, 0x20, 0x40] [0,8..]
let len = if coerce len' == 0 then 0x10000 else len'
-- FIXME add guard condition from `patch-delta.c`: if (unsigned_add_overflows(cp_off, cp_size) || ...
return $ (coerce offset, coerce len)
where calculateVal off shift = if shift /= 0 then (\x -> off .|. (x `shiftL` shift)::Int) . fromIntegral else fromIntegral
readIfBitSet off (test, shift) = if opcode .&. test /= 0 then liftM (calculateVal off shift) getWord8 else return off
coerce
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment