/// <summary>
        ///     Reads the next part of the database.
        /// </summary>
        /// <returns>true if there was a next part</returns>
        public bool Read()
        {
            if (_error)
            {
                throw new InvalidOperationException("An error has already been reported.");
            }

            if (CurrentPartType == PasswordSafePartType.None)
            {
                _error = true;
                throw new InvalidOperationException("No passphrase set");
            }

            if (CurrentPartType == PasswordSafePartType.End)
            {
                return(false);
            }

            if (CurrentPartType == PasswordSafePartType.Keys)
            {
                Header = ReadHeader();
                if (Header != null)
                {
                    CurrentPartType = PasswordSafePartType.Header;
                    return(true);
                }

                return(false);
            }

            if (CurrentPartType == PasswordSafePartType.Header || CurrentPartType == PasswordSafePartType.Record)
            {
                Record = ReadRecord();
                if (Record != null)
                {
                    CurrentPartType = PasswordSafePartType.Record;
                    return(true);
                }
            }

            ReadHmac();
            CurrentPartType = PasswordSafePartType.End;

            return(true);
        }
        /// <summary>
        ///     Reads one data record.
        /// </summary>
        /// <returns>The record</returns>
        private PasswordSafeRecord ReadRecord()
        {
            var fields = ReadGenericRecord();

            if (fields == null)
            {
                return(null);
            }

            var record  = new PasswordSafeRecord();
            var endSeen = false;

            foreach (var field in fields)
            {
                if (endSeen)
                {
                    throw new InvalidDataException("The END filed must be last in the header");
                }

                var data = field.DataBuffer();

                switch ((PasswordSafeRecordTypeCode)field.Type)
                {
                case PasswordSafeRecordTypeCode.NAME:
                    throw new InvalidDataException("The NAME field type is not allowed here.");

                case PasswordSafeRecordTypeCode.UUID:
                    if (data.Length != 16)
                    {
                        throw new InvalidDataException("UUID field length wrong");
                    }

                    record.Uuid = new Guid(data);
                    break;

                case PasswordSafeRecordTypeCode.GROUP:
                    record.Group =
                        Encoding.UTF8.GetString(data, 0, data.Length);     //.UTF8.GetString(data,0,data.Length);
                    break;

                case PasswordSafeRecordTypeCode.TITLE:
                    record.Title = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.USER:
                    record.User = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.NOTES:
                    record.Notes = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.PASSWORD:
                    record.PasswordValue = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.CTIME:
                    record.TimeRecordCreatedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.PMTIME:
                    record.TimePasswordModifiedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.ATIME:
                    record.TimeRecordAccessedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.LTIME:
                    record.TimePasswordExpiresUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.POLICY:
                    throw new InvalidDataException("The POLICY field type is not allowed here.");

                case PasswordSafeRecordTypeCode.RMTIME:
                    record.TimeRecordModifiedUtc = GetUtcFromUnixTime(data);
                    break;

                case PasswordSafeRecordTypeCode.URL:
                    record.ResourceLocator = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.AUTOTYPE:
                    record.AutoType = Encoding.UTF8.GetString(data, 0, data.Length);
                    break;

                case PasswordSafeRecordTypeCode.PWHIST:
                    var serializedHistory = Encoding.UTF8.GetString(data, 0, data.Length);
                    record.PasswordHistory = PasswordSafePasswordHistory.Parse(serializedHistory);
                    break;

                case PasswordSafeRecordTypeCode.END:
                    endSeen = true;
                    break;

                default:
                    record.UnknownFieldEntriesAdd(field);
                    break;
                }
            }

            return(record);
        }