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;
}