module Rattletrap.Decode.Section
  ( decodeSection
  )
where

import Rattletrap.Decode.Common
import Rattletrap.Decode.Word32le
import Rattletrap.Type.Section
import Rattletrap.Type.Word32le
import Rattletrap.Utility.Crc

import qualified Control.Monad as Monad

decodeSection :: Decode a -> Decode (Section a)
decodeSection :: Decode a -> Decode (Section a)
decodeSection Decode a
getBody = do
  Word32le
size <- Decode Word32le
decodeWord32le
  Word32le
crc <- Decode Word32le
decodeWord32le
  ByteString
rawBody <- Int -> Get ByteString
getByteString (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32le -> Word32
word32leValue Word32le
size))
  let actualCrc :: Word32le
actualCrc = Word32 -> Word32le
Word32le (ByteString -> Word32
getCrc32 ByteString
rawBody)
  Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.when (Word32le
actualCrc Word32le -> Word32le -> Bool
forall a. Eq a => a -> a -> Bool
/= Word32le
crc) (String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (Word32le -> Word32le -> String
crcMessage Word32le
actualCrc Word32le
crc))
  a
body <- (String -> Decode a)
-> (a -> Decode a) -> Either String a -> Decode a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Decode a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail a -> Decode a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Decode a -> ByteString -> Either String a
forall a. Decode a -> ByteString -> Either String a
runDecode Decode a
getBody ByteString
rawBody)
  Section a -> Decode (Section a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word32le -> Word32le -> a -> Section a
forall a. Word32le -> Word32le -> a -> Section a
Section Word32le
size Word32le
crc a
body)

crcMessage :: Word32le -> Word32le -> String
crcMessage :: Word32le -> Word32le -> String
crcMessage Word32le
actual Word32le
expected = [String] -> String
unwords
  [ String
"[RT10] actual CRC"
  , Word32le -> String
forall a. Show a => a -> String
show Word32le
actual
  , String
"does not match expected CRC"
  , Word32le -> String
forall a. Show a => a -> String
show Word32le
expected
  ]