private void SkipAttribute(DataReader mReader)
        {
            ulong size = mReader.ReadPackedUInt64();
            if(size > (ulong)mReader.Remaining)
                throw new InvalidDataException();

            mReader.Skip((long)size);
        }
        private void ReadHeader(DataReader mReader)
        {
            byte[] signature = mReader.ReadBytes(kSignature.Length);
            if(signature.Length != kSignature.Length)
                throw new InvalidDataException();
            for(int i = 0; i < signature.Length; i++)
                if(signature[i] != kSignature[i])
                    throw new InvalidDataException();

            mMajorVersion = mReader.ReadByte();
            mMinorVersion = mReader.ReadByte();

            if(mMajorVersion != 0)
                throw new NotSupportedException();

            // TODO: Weak check of supported minor versions

            uint startHeaderCRC = mReader.ReadUInt32();
            long nextHeaderOffset = mReader.ReadInt64();
            long nextHeaderLength = mReader.ReadInt64();
            uint nextHeaderCRC = mReader.ReadUInt32();

            Utils.Assert(mReader.Position == kPrimaryHeaderSize);

            if(mCheckCRC)
            {
                uint crc = CRC.kInitCRC;
                crc = CRC.Update(crc, nextHeaderOffset);
                crc = CRC.Update(crc, nextHeaderLength);
                crc = CRC.Update(crc, nextHeaderCRC);
                crc = CRC.Finish(crc);
                if(crc != startHeaderCRC)
                    throw new InvalidDataException();
            }

            if(nextHeaderLength < 0 || nextHeaderOffset < 0
                || nextHeaderOffset > mReader.Remaining - nextHeaderLength)
                throw new InvalidDataException();

            if(nextHeaderLength > 0) // zero is ok, empty archive
            {
                mReader.Skip(nextHeaderOffset);

                if(mCheckCRC)
                {
                    if(mReader.CalculateCRC(nextHeaderLength) != nextHeaderCRC)
                        throw new InvalidDataException();

                    mReader.Seek(kPrimaryHeaderSize + nextHeaderOffset);
                }

                using(mReader.Constrain(nextHeaderLength))
                    ReadHeader2(mReader);
            }
        }