gltf-codec-0.1.0.1: src/Codec/GLB.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
module Codec.GLB where
import Prelude hiding (length)
import Data.Binary (Binary(..), decodeFileOrFail)
import Data.Binary.Get (ByteOffset, getWord32le, getByteString, isEmpty)
import Data.Binary.Put (putByteString, putWord32le)
import Data.ByteString (ByteString)
import Data.Vector (Vector, unfoldrM)
import Data.Word (Word32)
import GHC.Generics (Generic)
fromFile :: FilePath -> IO (Either (ByteOffset, String) GLB)
fromFile = decodeFileOrFail
data GLB = GLB
{ header :: Header
, chunks :: Vector Chunk
} deriving (Eq, Show, Generic)
instance Binary GLB where
get = GLB <$> get <*> unfoldrM getChunks ()
where
getChunks () = do
done <- isEmpty
if done then
pure Nothing
else do
chunk <- get
pure $ Just (chunk, ())
put GLB{..} = do
put header
mapM_ put chunks
data Header = Header
{ magic :: Word32
, version :: Word32
, length :: Word32
} deriving (Eq, Show, Generic)
instance Binary Header where
get = Header
<$> getWord32le
<*> getWord32le
<*> getWord32le
put Header{..} = do
putWord32le magic
putWord32le version
putWord32le length
data Chunk = Chunk
{ chunkLength :: Word32
, chunkType :: Word32
, chunkData :: ByteString
}
deriving (Eq, Show, Generic)
instance Binary Chunk where
get = do
chunkLength <- getWord32le
chunkType <- getWord32le
chunkData <- getByteString (fromIntegral chunkLength)
pure Chunk{..}
put Chunk{..} = do
putWord32le chunkLength
putWord32le chunkType
putByteString chunkData