static bool ReadAMFObjectField()

in src/brpc/amf.cpp [384:499]


static bool ReadAMFObjectField(AMFInputStream* stream,
                               google::protobuf::Message* message,
                               const google::protobuf::FieldDescriptor* field) {
    const google::protobuf::Reflection* reflection = NULL;
    if (field) {
        reflection = message->GetReflection();
    }
    uint8_t marker;
    if (stream->cut_u8(&marker) != 1u) {
        LOG(ERROR) << "stream is not long enough";
        return false;
    }
    switch ((AMFMarker)marker) {
    case AMF_MARKER_NUMBER: {
        uint64_t val = 0;
        if (stream->cut_u64(&val) != 8u) {
            LOG(ERROR) << "stream is not long enough";
            return false;
        }
        if (field) {
            if (field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE) {
                LOG(WARNING) << "Can't set double=" << val << " to "
                             << field->full_name();
            } else {
                double* dptr = (double*)&val;
                reflection->SetDouble(message, field, *dptr);
            }
        }
    } break;
    case AMF_MARKER_BOOLEAN: {
        uint8_t val = 0;
        if (stream->cut_u8(&val) != 1u) {
            LOG(ERROR) << "stream is not long enough";
            return false;
        }
        if (field) {
            if (field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_BOOL) {
                LOG(WARNING) << "Can't set bool to " << field->full_name();
            } else {
                reflection->SetBool(message, field, !!val);
            }
        }
    } break;
    case AMF_MARKER_STRING: {
        std::string val;
        if (!ReadAMFShortStringBody(&val, stream)) {
            return false;
        }
        if (field) {
            if (field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
                LOG(WARNING) << "Can't set string=`" << val << "' to "
                           << field->full_name();
            } else {
                reflection->SetString(message, field, val);
            }
        }
    } break;
    case AMF_MARKER_TYPED_OBJECT: {
        std::string class_name;
        if (!ReadAMFShortStringBody(&class_name, stream)) {
            LOG(ERROR) << "Fail to read class_name";
        }
    }
    // fall through
    case AMF_MARKER_OBJECT: {
        if (field) {
            if (field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
                LOG(WARNING) << "Can't set object to " << field->full_name();
            } else {
                google::protobuf::Message* m = reflection->MutableMessage(message, field);
                if (!ReadAMFObjectBody(m, stream)) {
                    return false;
                }
            }
        } else {
            if (!SkipAMFObjectBody(stream)) {
                return false;
            }
        }
    } break;
    case AMF_MARKER_NULL:
    case AMF_MARKER_UNDEFINED:
    case AMF_MARKER_UNSUPPORTED:
        // Nothing to do
        break;
    case AMF_MARKER_MOVIECLIP:
    case AMF_MARKER_REFERENCE:
    case AMF_MARKER_ECMA_ARRAY:
    case AMF_MARKER_STRICT_ARRAY:
    case AMF_MARKER_DATE:
    case AMF_MARKER_RECORDSET:
    case AMF_MARKER_XML_DOCUMENT:
    case AMF_MARKER_AVMPLUS_OBJECT:
        LOG(ERROR) << marker2str(marker) << " is not supported yet";
        return false;
    case AMF_MARKER_OBJECT_END:
        CHECK(false) << "object-end shouldn't be present here";
        return false;
    case AMF_MARKER_LONG_STRING: {
        std::string val;
        if (!ReadAMFLongStringBody(&val, stream)) {
            LOG(ERROR) << "stream is not long enough";
            return false;
        }
        if (field) {
            if (field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
                LOG(WARNING) << "Can't set string=`" << val << "' to "
                             << field->full_name();
            } else {
                reflection->SetString(message, field, val);
            }
        }
    } break;
    } // switch
    return true;
}