/// <summary>
        /// Reads a BsonType from the reader.
        /// </summary>
        /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
        /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
        /// <param name="found">Set to true if a matching value was found in the trie.</param>
        /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
        /// <returns>A BsonType.</returns>
        public override BsonType ReadBsonType <TValue>(BsonTrie <TValue> bsonTrie, out bool found, out TValue value)
        {
            if (Disposed)
            {
                ThrowObjectDisposedException();
            }
            found = false;
            value = default(TValue);
            if (State == BsonReaderState.Initial || State == BsonReaderState.Done || State == BsonReaderState.ScopeDocument)
            {
                // there is an implied type of Document for the top level and for scope documents
                CurrentBsonType = BsonType.Document;
                State           = BsonReaderState.Value;
                return(CurrentBsonType);
            }
            if (State != BsonReaderState.Type)
            {
                ThrowInvalidState("ReadBsonType", BsonReaderState.Type);
            }

            CurrentBsonType = _buffer.ReadBsonType();

            if (CurrentBsonType == BsonType.EndOfDocument)
            {
                switch (_context.ContextType)
                {
                case ContextType.Array:
                    State = BsonReaderState.EndOfArray;
                    return(BsonType.EndOfDocument);

                case ContextType.Document:
                case ContextType.ScopeDocument:
                    State = BsonReaderState.EndOfDocument;
                    return(BsonType.EndOfDocument);

                default:
                    var message = string.Format("BsonType EndOfDocument is not valid when ContextType is {0}.", _context.ContextType);
                    throw new FileFormatException(message);
                }
            }
            else
            {
                switch (_context.ContextType)
                {
                case ContextType.Array:
                    _buffer.SkipCString();     // ignore array element names
                    State = BsonReaderState.Value;
                    break;

                case ContextType.Document:
                case ContextType.ScopeDocument:
                    CurrentName = _buffer.ReadName(bsonTrie, out found, out value);
                    State       = BsonReaderState.Name;
                    break;

                default:
                    throw new BsonInternalException("Unexpected ContextType.");
                }

                return(CurrentBsonType);
            }
        }