StatusWith<ServerSelectionMetadata> ServerSelectionMetadata::readFromMetadata(
    const BSONObj& metadata) {
    auto secondaryOkField = metadata.getField(kSecondaryOkFieldName);

    bool secondaryOk = !secondaryOkField.eoo();

    boost::optional<ReadPreferenceSetting> readPreference;
    BSONElement rpElem;
    auto readPrefExtractStatus =
        bsonExtractTypedField(metadata, kReadPreferenceFieldName, mongo::Object, &rpElem);

    if (readPrefExtractStatus == ErrorCodes::NoSuchKey) {
        // Do nothing, it's valid to have no ReadPreference
    } else if (!readPrefExtractStatus.isOK()) {
        return readPrefExtractStatus;
    } else {
        // We have a read preference in the metadata object.
        auto parsedRps = ReadPreferenceSetting::fromBSON(rpElem.Obj());
        if (!parsedRps.isOK()) {
            return parsedRps.getStatus();
        }
        readPreference.emplace(std::move(parsedRps.getValue()));
    }

    return ServerSelectionMetadata(secondaryOk, std::move(readPreference));
}
StatusWith<ServerSelectionMetadata> ServerSelectionMetadata::readFromMetadata(
    const BSONElement& metadataElem) {
    if (metadataElem.eoo()) {
        return ServerSelectionMetadata{};
    } else if (metadataElem.type() != mongo::Object) {
        return {ErrorCodes::TypeMismatch,
                str::stream() << "ServerSelectionMetadata element has incorrect type: expected"
                              << mongo::Object
                              << " but got "
                              << metadataElem.type()};
    }

    bool secondaryOk = false;
    boost::optional<ReadPreferenceSetting> readPreference;
    BSONElement rpElem;
    for (const auto& ssmElem : metadataElem.Obj()) {
        auto ssmElemFieldName = ssmElem.fieldNameStringData();
        if (ssmElemFieldName == kSecondaryOkFieldName) {
            secondaryOk = ssmElem.trueValue();
        } else if (ssmElemFieldName == kReadPreferenceFieldName) {
            if (ssmElem.type() != mongo::Object) {
                return Status(ErrorCodes::TypeMismatch,
                              str::stream() << "ReadPreference has incorrect type: expected"
                                            << mongo::Object
                                            << "but got"
                                            << metadataElem.type());
            }
            auto parsedRps = ReadPreferenceSetting::fromBSON(ssmElem.Obj());
            if (!parsedRps.isOK()) {
                return parsedRps.getStatus();
            }
            readPreference.emplace(std::move(parsedRps.getValue()));
        }
    }

    return ServerSelectionMetadata(secondaryOk, std::move(readPreference));
}