private function readManifest()
    {
        $size = unpack('V', $this->read(4));
        $size = $size[1];

        $raw = $this->read($size);

        // ++ start skip: API version, global flags, alias, and metadata
        $count = unpack('V', substr($raw, 0, 4));
        $count = $count[1];

        $aliasSize = unpack('V', substr($raw, 10, 4));
        $aliasSize = $aliasSize[1];
        $raw = substr($raw, 14 + $aliasSize);

        $metaSize = unpack('V', substr($raw, 0, 4));
        $metaSize = $metaSize[1];

        $offset = 0;
        $start = 4 + $metaSize;
        // -- end skip

        $manifest = array(
            'files' => array(),
            'flags' => 0,
        );

        for ($i = 0; $i < $count; $i++) {
            $length = unpack('V', substr($raw, $start, 4));
            $length = $length[1];
            $start += 4;

            $path = substr($raw, $start, $length);
            $start += $length;

            $file = unpack(
                'Vsize/Vtimestamp/Vcompressed_size/Vcrc32/Vflags/Vmetadata_length',
                substr($raw, $start, 24)
            );

            $file['path'] = $path;
            $file['crc32'] = sprintf('%u', $file['crc32'] & 0xffffffff);
            $file['offset'] = $offset;

            $offset += $file['compressed_size'];
            $start += 24 + $file['metadata_length'];

            $manifest['flags'] |= $file['flags'] & self::MASK;

            $manifest['files'][] = $file;
        }

        return $manifest;
    }