diff --git a/mmtf.cabal b/mmtf.cabal
--- a/mmtf.cabal
+++ b/mmtf.cabal
@@ -1,5 +1,5 @@
 name:                mmtf
-version:             0.1.1.0
+version:             0.1.2.0
 synopsis:            Macromolecular Transmission Format implementation
 description:         Haskell implementation of MMTF biological structure format.
 homepage:            https://github.com/zmactep/mmtf#readme
@@ -34,12 +34,24 @@
 test-suite mmtf-test
   type:                exitcode-stdio-1.0
   hs-source-dirs:      test
+                     , src
   main-is:             Spec.hs
+  other-modules:       Bio.MMTF
+                     , Bio.MMTF.Type
+                     , Bio.MMTF.MessagePack
+                     , Bio.MMTF.Decode
+                     , Bio.MMTF.Decode.Codec
+                     , Bio.MMTF.Decode.MessagePack
   build-depends:       base
                      , mmtf
-                     , QuickCheck >= 2.9.2 && < 2.10
-                     , hspec >= 2.4.1 && < 2.5
+                     , QuickCheck >= 2.9.2 && < 2.13
+                     , hspec >= 2.4.1 && < 2.7
+                     , data-msgpack
+                     , text
                      , bytestring
+                     , binary
+                     , containers
+                     , http-conduit
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N
   default-language:    Haskell2010
 
diff --git a/src/Bio/MMTF/Decode.hs b/src/Bio/MMTF/Decode.hs
--- a/src/Bio/MMTF/Decode.hs
+++ b/src/Bio/MMTF/Decode.hs
@@ -7,6 +7,7 @@
 import           Bio.MMTF.Type
 
 import           Control.Monad               ((>=>))
+import           Data.ByteString.Lazy        (empty)
 import           Data.Map.Strict             (Map)
 import           Data.MessagePack            (Object)
 import           Data.Text                   (Text)
@@ -27,76 +28,76 @@
 --
 chainData :: Monad m => Map Text Object -> m ChainData
 chainData mp = do gpc <- atP mp "groupsPerChain" asIntList
-                  cil <- codec5 . parseBinary <$> atP mp "chainIdList" asBinary
-                  cnl <- (codec5 . parseBinary <$>) <$> atPM mp "chainNameList" asBinary
+                  cil <- codec5 . parseBinary <$> atP   mp "chainIdList"   asBinary
+                  cnl <- codec5 . parseBinary <$> atPMD mp "chainNameList" asBinary empty
                   pure $ ChainData gpc cil cnl
 
 -- | Parses atom data from ObjectMap
 --
 atomData :: Monad m => Map Text Object -> m AtomData
-atomData mp = do ail' <- (codec8 . parseBinary <$>) <$> atPM mp "atomIdList" asBinary
-                 all' <- (codec6 . parseBinary <$>) <$> atPM mp "altLocList" asBinary
-                 bfl' <- (codec10 . parseBinary <$>) <$> atPM mp "bFactorList" asBinary
-                 xcl' <- codec10 . parseBinary <$> atP mp "xCoordList" asBinary
-                 ycl' <- codec10 . parseBinary <$> atP mp "yCoordList" asBinary
-                 zcl' <- codec10 . parseBinary <$> atP mp "zCoordList" asBinary
-                 ol' <-  (codec9 . parseBinary <$>) <$> atPM mp "occupancyList" asBinary
+atomData mp = do ail' <-  codec8 . parseBinary <$> atPMD mp "atomIdList"    asBinary empty
+                 all' <-  codec6 . parseBinary <$> atPMD mp "altLocList"    asBinary empty
+                 bfl' <- codec10 . parseBinary <$> atPMD mp "bFactorList"   asBinary empty
+                 xcl' <- codec10 . parseBinary <$> atP   mp "xCoordList"    asBinary
+                 ycl' <- codec10 . parseBinary <$> atP   mp "yCoordList"    asBinary
+                 zcl' <- codec10 . parseBinary <$> atP   mp "zCoordList"    asBinary
+                 ol' <-   codec9 . parseBinary <$> atPMD mp "occupancyList" asBinary empty
                  pure $ AtomData ail' all' bfl' xcl' ycl' zcl' ol'
 
 -- | Parses group data from ObjectMap
 --
 groupData :: Monad m => Map Text Object -> m GroupData
 groupData mp = do gl' <- atP mp "groupList" asObjectList >>= traverse (transformObjectMap >=> groupType)
-                  gtl' <- codec4 . parseBinary <$> atP mp "groupTypeList" asBinary
-                  gil' <- codec8 . parseBinary <$> atP mp "groupIdList" asBinary
-                  ssl' <- (map ssDec . codec2 . parseBinary <$>) <$> atPM mp "secStructList" asBinary
-                  icl' <- (codec6 . parseBinary <$>) <$> atPM mp "insCodeList" asBinary
-                  sil' <- (codec8 . parseBinary <$>) <$> atPM mp "sequenceIndexList" asBinary
+                  gtl' <-              codec4 . parseBinary <$> atP   mp "groupTypeList"     asBinary
+                  gil' <-              codec8 . parseBinary <$> atP   mp "groupIdList"       asBinary
+                  ssl' <- fmap ssDec . codec2 . parseBinary <$> atPMD mp "secStructList"     asBinary empty
+                  icl' <-              codec6 . parseBinary <$> atPMD mp "insCodeList"       asBinary empty
+                  sil' <-              codec8 . parseBinary <$> atPMD mp "sequenceIndexList" asBinary empty
                   pure $ GroupData gl' gtl' gil' ssl' icl' sil'
 
 -- | Parses group type from ObjectMap
 --
 groupType :: Monad m => Map Text Object -> m GroupType
 groupType mp = do fcl' <- atP mp "formalChargeList" asIntList
-                  anl' <- atP mp "atomNameList" asStrList
-                  el'  <- atP mp "elementList" asStrList
-                  bal' <- atP mp "bondAtomList" asIntList
-                  bol' <- atP mp "bondOrderList" asIntList
-                  gn'  <- atP mp "groupName" asStr
+                  anl' <- atP mp "atomNameList"     asStrList
+                  el'  <- atP mp "elementList"      asStrList
+                  bal' <- atP mp "bondAtomList"     asIntList
+                  bol' <- atP mp "bondOrderList"    asIntList
+                  gn'  <- atP mp "groupName"        asStr
                   slc' <- atP mp "singleLetterCode" asChar
-                  cct' <- atP mp "chemCompType" asStr
+                  cct' <- atP mp "chemCompType"     asStr
                   pure $ GroupType fcl' anl' el' bal' bol' gn' slc' cct'
 
 -- | Parses structure data from ObjectMap
 --
 structureData :: Monad m => Map Text Object -> m StructureData
-structureData mp = do ttl' <- atPM mp "title" asStr
-                      sid' <- atPM mp "structureId" asStr
-                      dd'  <- atPM mp "depositionDate" asStr
-                      rd'  <- atPM mp "releaseDate" asStr
-                      nb'  <- atP mp "numBonds" asInt
-                      na'  <- atP mp "numAtoms" asInt
-                      ng'  <- atP mp "numGroups" asInt
-                      nc'  <- atP mp "numChains" asInt
-                      nm'  <- atP mp "numModels" asInt
-                      sg'  <- atPM mp "spaceGroup" asStr
-                      uc'  <- (>>= ucDec) <$> atPM mp "unitCell" asFloatList
-                      nol' <- ((>>= asFloatList) <$>) <$> atPM mp "ncsOperatorList" asObjectList
-                      bal' <- (>>= traverse (transformObjectMap >=> bioAssembly)) <$> atPM mp "bioAssemblyList" asObjectList
-                      el'  <- (>>= traverse (transformObjectMap >=> entity)) <$> atPM mp "entityList" asObjectList
-                      res' <- atPM mp "resolution" asFloat
-                      rf'  <- atPM mp "rFree" asFloat
-                      rw'  <- atPM mp "rWork" asFloat
-                      em'  <- atPM mp "experimentalMethods" asStrList
-                      btl' <- (codec4 . parseBinary <$>) <$> atPM mp "bondAtomList" asBinary
-                      bol' <- (codec2 . parseBinary <$>) <$> atPM mp "bondOrderList" asBinary
+structureData mp = do ttl' <-                          atPMD mp "title"               asStr        ""
+                      sid' <-                          atPMD mp "structureId"         asStr        ""
+                      dd'  <-                          atPMD mp "depositionDate"      asStr        ""
+                      rd'  <-                          atPMD mp "releaseDate"         asStr        ""
+                      nb'  <-                          atP   mp "numBonds"            asInt
+                      na'  <-                          atP   mp "numAtoms"            asInt
+                      ng'  <-                          atP   mp "numGroups"           asInt
+                      nc'  <-                          atP   mp "numChains"           asInt
+                      nm'  <-                          atP   mp "numModels"           asInt
+                      sg'  <-                          atPMD mp "spaceGroup"          asStr        ""
+                      uc'  <-          (>>= ucDec) <$> atPM  mp "unitCell"            asFloatList
+                      nol' <-    (>>= asFloatList) <$> atPMD mp "ncsOperatorList"     asObjectList []
+                      bal' <-                          atPMD mp "bioAssemblyList"     asObjectList [] >>= traverse (transformObjectMap >=> bioAssembly)
+                      el'  <-                          atPMD mp "entityList"          asObjectList [] >>= traverse (transformObjectMap >=> entity)
+                      res' <-                          atPM  mp "resolution"          asFloat
+                      rf'  <-                          atPM  mp "rFree"               asFloat
+                      rw'  <-                          atPM  mp "rWork"               asFloat
+                      em'  <-                          atPMD mp "experimentalMethods" asStrList []
+                      btl' <- codec4 . parseBinary <$> atPMD mp "bondAtomList"        asBinary empty
+                      bol' <- codec2 . parseBinary <$> atPMD mp "bondOrderList"       asBinary empty
                       pure $ StructureData ttl' sid' dd' rd' nb' na' ng' nc' nm' sg' uc' nol'
                                            bal' el' res' rf' rw' em' btl' bol'
 
 -- | Parses bio assembly data from ObjectMap
 --
 bioAssembly :: Monad m => Map Text Object -> m Assembly
-bioAssembly mp = do nme' <- atP mp "name" asStr
+bioAssembly mp = do nme' <- atP mp "name"          asStr
                     tlt' <- atP mp "transformList" asObjectList >>= traverse (transformObjectMap >=> transform)
                     pure $ Assembly tlt' nme'
 
@@ -104,14 +105,14 @@
 --
 transform :: Monad m => Map Text Object -> m Transform
 transform mp = do cil' <- atP mp "chainIndexList" asIntList
-                  mtx' <- atP mp "matrix" asFloatList
+                  mtx' <- atP mp "matrix"         asFloatList
                   pure $ Transform cil' mtx'
 
 -- | Parses entity data from ObjectMap
 --
 entity :: Monad m => Map Text Object -> m Entity
 entity mp = do cil' <- atP mp "chainIndexList" asIntList
-               dsc' <- atP mp "description" asStr
-               tpe' <- atP mp "type" asStr
-               sqc' <- atP mp "sequence" asStr
+               dsc' <- atP mp "description"    asStr
+               tpe' <- atP mp "type"           asStr
+               sqc' <- atP mp "sequence"       asStr
                pure $ Entity cil' dsc' tpe' sqc'
diff --git a/src/Bio/MMTF/Decode/MessagePack.hs b/src/Bio/MMTF/Decode/MessagePack.hs
--- a/src/Bio/MMTF/Decode/MessagePack.hs
+++ b/src/Bio/MMTF/Decode/MessagePack.hs
@@ -24,6 +24,12 @@
 atPM :: Monad m => Map Text Object -> Text -> (Object -> m a) -> m (Maybe a)
 atPM m k conv = traverse conv $ M.lookup k m
 
+atPMD :: Monad m => Map Text Object -> Text -> (Object -> m a) -> a -> m a
+atPMD m k conv def = do x <- atPM m k conv
+                        case x of
+                          Just r  -> pure r
+                          Nothing -> pure def
+                       
 asStr :: Monad m => Object -> m Text
 asStr (ObjectStr s) = pure s
 asStr _             = fail "Not a string data"
diff --git a/src/Bio/MMTF/Type.hs b/src/Bio/MMTF/Type.hs
--- a/src/Bio/MMTF/Type.hs
+++ b/src/Bio/MMTF/Type.hs
@@ -72,26 +72,26 @@
 
 -- | Structure data
 --
-data StructureData = StructureData { title               :: !(Maybe Text)       -- ^ A short description of the structural data included in the file
-                                   , structureId         :: !(Maybe Text)       -- ^ An ID for the structure, for example the PDB ID if applicable
-                                   , depositionDate      :: !(Maybe Text)       -- ^ A date that relates to the deposition of the structure in a database
-                                   , releaseDate         :: !(Maybe Text)       -- ^ A date that relates to the release of the structure in a database
+data StructureData = StructureData { title               :: !Text               -- ^ A short description of the structural data included in the file
+                                   , structureId         :: !Text               -- ^ An ID for the structure, for example the PDB ID if applicable
+                                   , depositionDate      :: !Text               -- ^ A date that relates to the deposition of the structure in a database
+                                   , releaseDate         :: !Text               -- ^ A date that relates to the release of the structure in a database
                                    , numBonds            :: !Int32              -- ^ The overall number of bonds
                                    , numAtoms            :: !Int32              -- ^ The overall number of atoms in the structure
                                    , numGroups           :: !Int32              -- ^ The overall number of groups in the structure
                                    , numChains           :: !Int32              -- ^ The overall number of chains in the structure
                                    , numModels           :: !Int32              -- ^ The overall number of models in the structure
-                                   , spaceGroup          :: !(Maybe Text)       -- ^ The Hermann-Mauguin space-group symbol
+                                   , spaceGroup          :: !Text               -- ^ The Hermann-Mauguin space-group symbol
                                    , unitCell            :: !(Maybe UnitCell)   -- ^ Array of six values defining the unit cell
-                                   , ncsOperatorList     :: !(Maybe [[Float]])  -- ^ List of lists representing 4x4 transformation matrices that are stored linearly in row major order (transformation matrices describe noncrystallographic symmetry operations needed to create all molecules in the unit cell)
-                                   , bioAssemblyList     :: !(Maybe [Assembly]) -- ^ List of instructions on how to transform coordinates for an array of chains to create (biological) assemblies
-                                   , entityList          :: !(Maybe [Entity])   -- ^ List of unique molecular entities within the structure
+                                   , ncsOperatorList     :: ![[Float]]          -- ^ List of lists representing 4x4 transformation matrices that are stored linearly in row major order (transformation matrices describe noncrystallographic symmetry operations needed to create all molecules in the unit cell)
+                                   , bioAssemblyList     :: ![Assembly]         -- ^ List of instructions on how to transform coordinates for an array of chains to create (biological) assemblies
+                                   , entityList          :: ![Entity]           -- ^ List of unique molecular entities within the structure
                                    , resolution          :: !(Maybe Float)      -- ^ The experimental resolution in Angstrom
                                    , rFree               :: !(Maybe Float)      -- ^ The R-free value
                                    , rWork               :: !(Maybe Float)      -- ^ The R-work value
-                                   , experimentalMethods :: !(Maybe [Text])     -- ^ List of experimental methods employed for structure determination
-                                   , bondAtomList        :: !(Maybe [Int32])    -- ^ Pairs of values represent indices of covalently bonded atoms [binary (type 4)]
-                                   , bondOrderList       :: !(Maybe [Int8])     -- ^ List of bond orders for bonds in 'bondAtomList' [binary (type 2)]
+                                   , experimentalMethods :: ![Text]             -- ^ List of experimental methods employed for structure determination
+                                   , bondAtomList        :: ![Int32]            -- ^ Pairs of values represent indices of covalently bonded atoms [binary (type 4)]
+                                   , bondOrderList       :: ![Int8]             -- ^ List of bond orders for bonds in 'bondAtomList' [binary (type 2)]
                                    }
   deriving (Show, Eq)
 
@@ -105,7 +105,7 @@
 --
 data ChainData = ChainData { groupsPerChain :: ![Int32]        -- ^ List of the number of groups (aka residues) in each chain
                            , chainIdList    :: ![Text]         -- ^ List of chain IDs [binary (type 5)]
-                           , chainNameList  :: !(Maybe [Text]) -- ^ List of chain names [binary (type 5)]
+                           , chainNameList  :: ![Text]         -- ^ List of chain names [binary (type 5)]
                            }
   deriving (Show, Eq)
 
@@ -114,21 +114,21 @@
 data GroupData = GroupData { groupList         :: ![GroupType]                  -- ^ List of groupType objects
                            , groupTypeList     :: ![Int32]                      -- ^ List of pointers to 'groupType' entries in 'groupList' by their keys [binary (type 4)]
                            , groupIdList       :: ![Int32]                      -- ^ List of group (residue) numbers [binary (type 8)]
-                           , secStructList     :: !(Maybe [SecondaryStructure]) -- ^ List of secondary structure assignments [binary (type 2)]
-                           , insCodeList       :: !(Maybe [Char])               -- ^ List of insertion codes, one for each group (residue) [binary (type 6)]
-                           , sequenceIndexList :: !(Maybe [Int32])              -- ^ List of indices that point into the sequence property of an entity object in the 'entityList' field that is associated with the chain the group belongs to [binary (type 8)]
+                           , secStructList     :: ![SecondaryStructure]         -- ^ List of secondary structure assignments [binary (type 2)]
+                           , insCodeList       :: ![Char]                       -- ^ List of insertion codes, one for each group (residue) [binary (type 6)]
+                           , sequenceIndexList :: ![Int32]                      -- ^ List of indices that point into the sequence property of an entity object in the 'entityList' field that is associated with the chain the group belongs to [binary (type 8)]
                            }
   deriving (Show, Eq)
 
 -- | Atoms data
 --
-data AtomData = AtomData { atomIdList    :: !(Maybe [Int32]) -- ^ List of atom serial numbers [binary (type 8)]
-                         , altLocList    :: !(Maybe [Char])  -- ^ List of alternate location labels, one for each atom [binary (type 6)]
-                         , bFactorList   :: !(Maybe [Float]) -- ^ List of atom B-factors in in A^2, one for each atom [binary (type 10)]
+data AtomData = AtomData { atomIdList    :: ![Int32]         -- ^ List of atom serial numbers [binary (type 8)]
+                         , altLocList    :: ![Char]          -- ^ List of alternate location labels, one for each atom [binary (type 6)]
+                         , bFactorList   :: ![Float]         -- ^ List of atom B-factors in in A^2, one for each atom [binary (type 10)]
                          , xCoordList    :: ![Float]         -- ^ List of x atom coordinates in A, one for each atom [binary (type 10)]
                          , yCoordList    :: ![Float]         -- ^ List of y atom coordinates in A, one for each atom [binary (type 10)]
                          , zCoordList    :: ![Float]         -- ^ List of z atom coordinates in A, one for each atom [binary (type 10)]
-                         , occupancyList :: !(Maybe [Float]) -- ^ List of atom occupancies, one for each atom [binary (type 9)]
+                         , occupancyList :: ![Float]         -- ^ List of atom occupancies, one for each atom [binary (type 9)]
                          }
   deriving (Show, Eq)
 
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -2,13 +2,40 @@
 
 import           Bio.MMTF
 import qualified Data.ByteString.Lazy as B
+import           Data.Int             (Int8)
 import           Test.Hspec
 
+import Bio.MMTF.Decode.Codec
+
+codecSpec :: Spec
+codecSpec =
+  describe "MMTF decoding" $ do
+    it "unpacks by Run-length encoding" $ do
+      let sample = [ 1, 10, 2, 1, 1, 4 ] :: [Int8]
+      runLengthDec sample `shouldBe` ([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1 ] :: [Int8])
+    it "unpacks by Delta encoding" $ do
+      let sample = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1 ] :: [Int8]
+      deltaDec sample `shouldBe` ([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16 ] :: [Int8])
+    it "unpacks by Recursive indexing encoding" $ do
+      let sample = [ 127, 41, 34, 1, 0, -50, -128, 0, 7, 127, 0, 127, 127, 14 ] :: [Int8]
+      recIndexDec sample `shouldBe` [ 168, 34, 1, 0, -50, -128, 7, 127, 268 ]
+    it "upacks by Integer encoding" $ do
+      let sample = [ 100, 100, 100, 100, 50, 50 ] :: [Int8]
+      integerDec 100 sample `shouldBe` [ 1.00, 1.00, 1.00, 1.00, 0.50, 0.50 ]
+
+parserSpec :: Spec
+parserSpec =
+  describe "MMTF parser" $
+  it "should parse 1FSD" $ do
+    m <- fetch "1FSD"
+    (structureId . structure) m `shouldBe` "1FSD"
+    (numModels . structure) m `shouldBe` 41
+    (length . bFactorList . atom) m `shouldBe` 20664
+    (experimentalMethods . structure) m `shouldBe` ["SOLUTION NMR"]
+    (head . xCoordList . atom) m `shouldBe` (-12.847)
+    (last . xCoordList . atom) m `shouldBe` 5.672
+
 main :: IO ()
-main = hspec $
-  describe "MMTF" $
-    it "should parse 1FSD" $ do
-      contents <- B.readFile "resource/1FSD.mmtf"
-      m <- decode contents
-      (structureId . structure) m `shouldBe` Just "1FSD"
-      (numModels . structure) m `shouldBe` 41
+main = hspec $ do
+         codecSpec
+         parserSpec
