Handle<Object> ParsePart(const google::protobuf::Message &message) { HandleScope scope; const Reflection* r = message.GetReflection(); const Descriptor* descriptor = message.GetDescriptor(); Local<Array> properties = Array::New(descriptor->field_count()); for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); bool repeated = field->is_repeated(); if (repeated && !r->FieldSize(message, field)) continue; if (!repeated && !r->HasField(message, field)) continue; Handle<Value> value; if (field->is_repeated()) { int size = r->FieldSize(message, field); Handle<Array> array = Array::New(size); for (int j = 0; j < size; j++) array->Set(j, ParseField(message, r, field, j)); value = array; } else { value = ParseField(message, r, field, -1); } if (value->IsNull()) continue; properties->Set(i, value); } Local<Function> from_array = handle_->GetInternalField(2).As<Function>(); Handle<Value> args = properties; return scope.Close(from_array->NewInstance(1, &args)); }
Type(Protobuf* _protobuf, google::protobuf::Message *_message, Handle<Object> self, size_t _index) { protobuf = _protobuf; message = _message; descriptor = _message->GetDescriptor(); index = _index; // Generate functions for bulk conversion between a JS object // and an array in descriptor order: // from = function(arr) { this.f0 = arr[0]; this.f1 = arr[1]; ... } // to = function() { return [ this.f0, this.f1, ... ] } // This is faster than repeatedly calling Get/Set on a v8::Object. std::ostringstream from, to; from << "(function(arr) { if(arr) {"; to << "(function() { return [ "; for (int i = 0; i < descriptor->field_count(); i++) { std::string name = descriptor->field(i)->name(); from << "var x = arr[" << i << "]; if (x !== undefined) this['" << name << "'] = x; "; if (i > 0) to << ", "; to << "this['" << name << "']"; } from << " }})"; to << " ]; })"; // managed type->schema link self->SetInternalField(1, protobuf->handle_); self->SetInternalField(2, Script::Compile(String::New(from.str().c_str()))->Run()); self->SetInternalField(3, Script::Compile(String::New(to.str().c_str()))->Run()); Wrap(self); }
void SerializePart(google::protobuf::Message *message, Handle<Object> src) { Handle<Function> to_array = handle_->GetInternalField(3).As<Function>(); Handle<Array> properties = to_array->Call(src, 0, NULL).As<Array>(); const Reflection *r = message->GetReflection(); for (int i = 0; i < descriptor->field_count(); i++) { Local<Value> value = properties->Get(i); if (value->IsUndefined() || value->IsNull()) continue; const FieldDescriptor* field = descriptor->field(i); if (field->is_repeated()) { if (value->IsArray()) { Handle<Array> array = value.As<Array>(); int length = array->Length(); for (int j = 0; j < length; j++) SerializeField(message, r, field, array->Get(j)); } else if (value->IsObject() && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && field->message_type()->name().compare(0, 20, "KeyValuePair_String_") == 0) { Local<Object> object = value.As<Object>(); Local<Array> subProperties = object->GetOwnPropertyNames(); int len = subProperties->Length(); for (int keyIdx = 0; keyIdx < len; keyIdx++) { Local<Object> keyValuePair = Object::New(); Local<Value> key = subProperties->Get(keyIdx); keyValuePair->Set(KeySymbol, key); keyValuePair->Set(ValueSymbol, object->Get(key)); SerializeField(message, r, field, keyValuePair); } } } else { SerializeField(message, r, field, value); } } }