13d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// Copyright 2010 Google Inc.
23d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//
33d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// Licensed under the Apache License, Version 2.0 (the "License"); you
43d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// may not use this file except in compliance with the License.
53d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// You may obtain a copy of the License at
63d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//
73d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//     http://www.apache.org/licenses/LICENSE-2.0
83d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//
93d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// Unless required by applicable law or agreed to in writing, software
103d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// distributed under the License is distributed on an "AS IS" BASIS,
113d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
123d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// implied. See the License for the specific language governing
133d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville// permissions and limitations under the License.
143d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
153d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include "protobuf_v8.h"
163d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
173d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <map>
183d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <string>
193d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <iostream>
203d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <sstream>
213d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
223d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <google/protobuf/dynamic_message.h>
233d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <google/protobuf/descriptor.h>
243d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include <google/protobuf/descriptor.pb.h>
253d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
263d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include "logging.h"
279b92c6b4651e608125a48f8f06a7a840042e090dWink Saville#include "util.h"
289b92c6b4651e608125a48f8f06a7a840042e090dWink Saville
293d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include "node_buffer.h"
303d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include "node_object_wrap.h"
313d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
323d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#include "node_util.h"
333d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
343d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//#define PROTOBUF_V8_DEBUG
353d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#ifdef  PROTOBUF_V8_DEBUG
363d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
376464068a31ff890d42d3da9cdf580d07c9c630d8Steve Block#define DBG(...) ALOGD(__VA_ARGS__)
383d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
393d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#else
403d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
413d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#define DBG(...)
423d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
433d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#endif
443d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
453d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::Descriptor;
463d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::DescriptorPool;
473d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::DynamicMessageFactory;
483d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::FieldDescriptor;
493d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::FileDescriptorSet;
503d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::Message;
513d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing google::protobuf::Reflection;
523d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
533d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//using ObjectWrap;
543d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville//using Buffer;
553d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
563d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing std::map;
573d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing std::string;
583d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
593d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Array;
603d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::AccessorInfo;
613d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Arguments;
623d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Boolean;
633d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Context;
643d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::External;
653d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Function;
663d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::FunctionTemplate;
673d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Integer;
683d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Handle;
693d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::HandleScope;
703d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::InvocationCallback;
713d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Local;
723d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::NamedPropertyGetter;
733d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Number;
743d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Object;
753d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::ObjectTemplate;
763d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Persistent;
773d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Script;
783d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::String;
793d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::Value;
803d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleusing v8::V8;
813d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
823d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savillenamespace protobuf_v8 {
833d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
843d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  template <typename T>
853d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  static T* UnwrapThis(const Arguments& args) {
863d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    return ObjectWrap::Unwrap<T>(args.This());
873d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  }
883d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
893d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  template <typename T>
903d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  static T* UnwrapThis(const AccessorInfo& args) {
913d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    return ObjectWrap::Unwrap<T>(args.This());
923d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  }
933d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
943d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  Persistent<FunctionTemplate> SchemaTemplate;
953d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  Persistent<FunctionTemplate> TypeTemplate;
963d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  Persistent<FunctionTemplate> ParseTemplate;
973d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  Persistent<FunctionTemplate> SerializeTemplate;
983d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
993d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  class Schema : public ObjectWrap {
1003d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  public:
1013d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    Schema(Handle<Object> self, const DescriptorPool* pool)
1023d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        : pool_(pool) {
1033d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::Schema E:");
1043d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      factory_.SetDelegateToGeneratedFactory(true);
1053d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      self->SetInternalField(1, Array::New());
1063d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Wrap(self);
1073d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::Schema X:");
1083d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    }
1093d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1103d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    virtual ~Schema() {
1113d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("~Schema::Schema E:");
1123d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      if (pool_ != DescriptorPool::generated_pool())
1133d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        delete pool_;
1143d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("~Schema::Schema X:");
1153d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    }
1163d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1173d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    class Type : public ObjectWrap {
1183d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    public:
1193d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Schema* schema_;
1203d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      const Descriptor* descriptor_;
1213d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1223d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Message* NewMessage() const {
1233d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::NewMessage() EX:");
1243d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return schema_->NewMessage(descriptor_);
1253d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
1263d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1273d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Handle<Function> Constructor() const {
1283d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::Constrocutor() EX:");
1293d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return handle_->GetInternalField(2).As<Function>();
1303d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
1313d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1323d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Local<Object> NewObject(Handle<Value> properties) const {
1333d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::NewObjext(properties) EX:");
1343d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return Constructor()->NewInstance(1, &properties);
1353d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
1363d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1373d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Type(Schema* schema, const Descriptor* descriptor, Handle<Object> self)
1383d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        : schema_(schema), descriptor_(descriptor) {
1393d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::Type(schema, descriptor, self) E:");
1403d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        // Generate functions for bulk conversion between a JS object
1413d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        // and an array in descriptor order:
1423d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        //   from = function(arr) { this.f0 = arr[0]; this.f1 = arr[1]; ... }
1433d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        //   to   = function()    { return [ this.f0, this.f1, ... ] }
1443d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        // This is faster than repeatedly calling Get/Set on a v8::Object.
1453d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        std::ostringstream from, to;
1463d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        from << "(function(arr) { if(arr) {";
1473d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        to << "(function() { return [ ";
1483d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1493d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        for (int i = 0; i < descriptor->field_count(); i++) {
1503d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          from <<
1513d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            "var x = arr[" << i << "]; "
1523d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            "if(x !== undefined) this['" <<
1533d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            descriptor->field(i)->camelcase_name() <<
1543d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            "'] = x; ";
1553d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1563d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          if (i > 0) to << ", ";
1573d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          to << "this['" << descriptor->field(i)->camelcase_name() << "']";
1583d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("field name=%s", descriptor->field(i)->name().c_str());
1593d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
1603d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1613d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        from << " }})";
1623d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        to << " ]; })";
1633d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1643d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        // managed type->schema link
1653d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        self->SetInternalField(1, schema_->handle_);
1663d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1673d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Function> constructor =
1683d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          Script::Compile(String::New(from.str().c_str()))->Run().As<Function>();
1693d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        constructor->SetHiddenValue(String::New("type"), self);
1703d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1713d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Function> bind =
1723d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          Script::Compile(String::New(
1733d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              "(function(self) {"
1743d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              "  var f = this;"
1753d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              "  return function(arg) {"
1763d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              "    return f.call(self, arg);"
1773d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              "  };"
1783d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              "})"))->Run().As<Function>();
1793d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Value> arg = self;
1803d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        constructor->Set(String::New("parse"), bind->Call(ParseTemplate->GetFunction(), 1, &arg));
1813d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        constructor->Set(String::New("serialize"), bind->Call(SerializeTemplate->GetFunction(), 1, &arg));
1823d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        self->SetInternalField(2, constructor);
1833d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        self->SetInternalField(3, Script::Compile(String::New(to.str().c_str()))->Run());
1843d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1853d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Wrap(self);
1863d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::Type(schema, descriptor, self) X:");
1873d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
1883d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1893d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#define GET(TYPE)                                                        \
1903d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      (index >= 0 ?                                                      \
1913d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville       reflection->GetRepeated##TYPE(instance, field, index) :           \
1923d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville       reflection->Get##TYPE(instance, field))
1933d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
1943d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      static Handle<Value> ToJs(const Message& instance,
1953d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                                const Reflection* reflection,
1963d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                                const FieldDescriptor* field,
1973d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                                const Type* message_type,
1983d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                                int index) {
1993d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::ToJs(instance, refelction, field, message_type) E:");
2003d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        switch (field->cpp_type()) {
2013d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_MESSAGE:
2023d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_MESSAGE");
2033d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return message_type->ToJs(GET(Message));
2043d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_STRING: {
2053d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_STRING");
2063d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          const string& value = GET(String);
2073d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return String::New(value.data(), value.length());
2083d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
2093d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_INT32:
2103d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_INT32");
2113d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Integer::New(GET(Int32));
2123d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_UINT32:
2133d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_UINT32");
2143d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Integer::NewFromUnsigned(GET(UInt32));
2153d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_INT64:
2163d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_INT64");
2173d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Number::New(GET(Int64));
2183d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_UINT64:
2193d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_UINT64");
2203d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Number::New(GET(UInt64));
2213d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_FLOAT:
2223d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_FLOAT");
2233d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Number::New(GET(Float));
2243d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_DOUBLE:
2253d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_DOUBLE");
2263d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Number::New(GET(Double));
2273d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_BOOL:
2283d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_BOOL");
2293d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return Boolean::New(GET(Bool));
2303d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_ENUM:
2313d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs CPPTYPE_ENUM");
2323d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return String::New(GET(Enum)->name().c_str());
2333d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
2343d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2353d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return Handle<Value>();  // NOTREACHED
2363d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
2373d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#undef GET
2383d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2393d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Handle<Object> ToJs(const Message& instance) const {
2403d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::ToJs(Message) E:");
2413d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        const Reflection* reflection = instance.GetReflection();
2423d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        const Descriptor* descriptor = instance.GetDescriptor();
2433d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2443d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Array> properties = Array::New(descriptor->field_count());
2453d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        for (int i = 0; i < descriptor->field_count(); i++) {
2463d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          HandleScope scope;
2473d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2483d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          const FieldDescriptor* field = descriptor->field(i);
2493d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          bool repeated = field->is_repeated();
2503d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          if (repeated && !reflection->FieldSize(instance, field)) {
2513d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            DBG("Ignore repeated field with no size in reflection data");
2523d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            continue;
2533d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          }
2543d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          if (!repeated && !reflection->HasField(instance, field)) {
2553d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            DBG("Ignore field with no field in relfection data");
2563d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            continue;
2573d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          }
2583d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2593d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          const Type* child_type =
2603d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
2613d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            schema_->GetType(field->message_type()) : NULL;
2623d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2633d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          Handle<Value> value;
2643d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          if (field->is_repeated()) {
2653d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            int size = reflection->FieldSize(instance, field);
2663d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            Handle<Array> array = Array::New(size);
2673d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            for (int j = 0; j < size; j++) {
2683d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              array->Set(j, ToJs(instance, reflection, field, child_type, j));
2693d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            }
2703d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            value = array;
2713d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          } else {
2723d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            value = ToJs(instance, reflection, field, child_type, -1);
2733d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          }
2743d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2753d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToJs: set property[%d]=%s", i, ToCString(value));
2763d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          properties->Set(i, value);
2773d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
2783d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2793d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::ToJs(Message) X:");
2803d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return NewObject(properties);
2813d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
2823d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2833d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      static Handle<Value> Parse(const Arguments& args) {
2843d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::Parse(args) E:");
2853d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Type* type = UnwrapThis<Type>(args);
2863d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Buffer* buf = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
2873d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2883d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Message* message = type->NewMessage();
2893d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        message->ParseFromArray(buf->data(), buf->length());
2903d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Object> result = type->ToJs(*message);
2913d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        delete message;
2923d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2933d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::Parse(args) X:");
2943d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return result;
2953d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
2963d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
2973d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#define SET(TYPE, EXPR)                                                 \
2983d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      if (repeated) reflection->Add##TYPE(instance, field, EXPR);       \
2993d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      else reflection->Set##TYPE(instance, field, EXPR)
3003d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
3019b92c6b4651e608125a48f8f06a7a840042e090dWink Saville      static bool ToProto(Message* instance,
3023d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                          const FieldDescriptor* field,
3033d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                          Handle<Value> value,
3043d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                          const Type* type,
3053d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                          bool repeated) {
3063d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::ToProto(instance, field, value, type, repeated) E:");
3079b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        bool ok = true;
3083d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        HandleScope scope;
3093d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
3103d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Type::ToProto field->name()=%s", field->name().c_str());
3113d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        const Reflection* reflection = instance->GetReflection();
3123d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        switch (field->cpp_type()) {
3133d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_MESSAGE:
3143d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_MESSAGE");
3159b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          ok = type->ToProto(repeated ?
3169b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                                reflection->AddMessage(instance, field) :
3179b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                                reflection->MutableMessage(instance, field),
3189b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                                    value.As<Object>());
3193d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3203d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_STRING: {
3213d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_STRING");
3223d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          String::AsciiValue ascii(value);
3233d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(String, string(*ascii, ascii.length()));
3243d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3253d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
3263d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_INT32:
3273d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_INT32");
3283d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(Int32, value->NumberValue());
3293d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3303d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_UINT32:
3313d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_UINT32");
3323d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(UInt32, value->NumberValue());
3333d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3343d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_INT64:
3353d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_INT64");
3363d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(Int64, value->NumberValue());
3373d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3383d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_UINT64:
3393d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_UINT64");
3403d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(UInt64, value->NumberValue());
3413d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3423d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_FLOAT:
3433d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_FLOAT");
3443d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(Float, value->NumberValue());
3453d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3463d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_DOUBLE:
3473d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_DOUBLE");
3483d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(Double, value->NumberValue());
3493d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3503d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_BOOL:
3513d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_BOOL");
3523d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          SET(Bool, value->BooleanValue());
3533d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3543d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        case FieldDescriptor::CPPTYPE_ENUM:
3553d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Type::ToProto CPPTYPE_ENUM");
3569b92c6b4651e608125a48f8f06a7a840042e090dWink Saville
3579b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          // Don't use SET as vd can be NULL
3589b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          char error_buff[256];
3599b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          const google::protobuf::EnumValueDescriptor* vd;
3609b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          int i32_value = 0;
3619b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          const char *str_value = NULL;
3629b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          const google::protobuf::EnumDescriptor* ed = field->enum_type();
3639b92c6b4651e608125a48f8f06a7a840042e090dWink Saville
3649b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          if (value->IsNumber()) {
3659b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            i32_value = value->Int32Value();
3669b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            vd = ed->FindValueByNumber(i32_value);
3679b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            if (vd == NULL) {
3689b92c6b4651e608125a48f8f06a7a840042e090dWink Saville              snprintf(error_buff, sizeof(error_buff),
3699b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                  "Type::ToProto Bad enum value, %d is not a member of enum %s",
3709b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                      i32_value, ed->full_name().c_str());
3719b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            }
3729b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          } else {
3739b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            str_value = ToCString(value);
3749b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            // TODO: Why can str_value be corrupted sometimes?
3756464068a31ff890d42d3da9cdf580d07c9c630d8Steve Block            ALOGD("str_value=%s", str_value);
3769b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            vd = ed->FindValueByName(str_value);
3779b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            if (vd == NULL) {
3789b92c6b4651e608125a48f8f06a7a840042e090dWink Saville              snprintf(error_buff, sizeof(error_buff),
3799b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                  "Type::ToProto Bad enum value, %s is not a member of enum %s",
3809b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                      str_value, ed->full_name().c_str());
3819b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            }
3829b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          }
3839b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          if (vd != NULL) {
3849b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            if (repeated) {
3859b92c6b4651e608125a48f8f06a7a840042e090dWink Saville               reflection->AddEnum(instance, field, vd);
3869b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            } else {
3879b92c6b4651e608125a48f8f06a7a840042e090dWink Saville               reflection->SetEnum(instance, field, vd);
3889b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            }
3899b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          } else {
3909b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            v8::ThrowException(String::New(error_buff));
3919b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            ok = false;
3929b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          }
3933d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          break;
3943d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
3959b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        DBG("Type::ToProto(instance, field, value, type, repeated) X: ok=%d", ok);
3969b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        return ok;
3973d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
3983d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville#undef SET
3993d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4009b92c6b4651e608125a48f8f06a7a840042e090dWink Saville      bool ToProto(Message* instance, Handle<Object> src) const {
4013d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("ToProto(Message *, Handle<Object>) E:");
4029b92c6b4651e608125a48f8f06a7a840042e090dWink Saville
4033d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Function> to_array = handle_->GetInternalField(3).As<Function>();
4043d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Array> properties = to_array->Call(src, 0, NULL).As<Array>();
4059b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        bool ok = true;
4069b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        for (int i = 0; ok && (i < descriptor_->field_count()); i++) {
4073d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          Handle<Value> value = properties->Get(i);
4083d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          if (value->IsUndefined()) continue;
4093d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4103d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          const FieldDescriptor* field = descriptor_->field(i);
4113d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          const Type* child_type =
4123d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
4133d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            schema_->GetType(field->message_type()) : NULL;
4143d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          if (field->is_repeated()) {
4153d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            if(!value->IsArray()) {
4169b92c6b4651e608125a48f8f06a7a840042e090dWink Saville              ok = ToProto(instance, field, value, child_type, true);
4173d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            } else {
4183d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              Handle<Array> array = value.As<Array>();
4193d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              int length = array->Length();
4209b92c6b4651e608125a48f8f06a7a840042e090dWink Saville              for (int j = 0; ok && (j < length); j++) {
4219b92c6b4651e608125a48f8f06a7a840042e090dWink Saville                ok = ToProto(instance, field, array->Get(j), child_type, true);
4223d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville              }
4233d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville            }
4243d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          } else {
4259b92c6b4651e608125a48f8f06a7a840042e090dWink Saville            ok = ToProto(instance, field, value, child_type, false);
4263d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          }
4273d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
4289b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        DBG("ToProto(Message *, Handle<Object>) X: ok=%d", ok);
4299b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        return ok;
4303d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
4313d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4323d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      static Handle<Value> Serialize(const Arguments& args) {
4339b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        Handle<Value> result;
4343d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Serialize(Arguments&) E:");
4353d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        if (!args[0]->IsObject()) {
4363d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          DBG("Serialize(Arguments&) X: not an object");
4373d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville          return v8::ThrowException(args[0]);
4383d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        }
4393d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4403d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Type* type = UnwrapThis<Type>(args);
4413d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Message* message = type->NewMessage();
4429b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        if (type->ToProto(message, args[0].As<Object>())) {
4439b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          int length = message->ByteSize();
4449b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          Buffer* buffer = Buffer::New(length);
4459b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          message->SerializeWithCachedSizesToArray((google::protobuf::uint8*)buffer->data());
4469b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          delete message;
4479b92c6b4651e608125a48f8f06a7a840042e090dWink Saville
4489b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          result = buffer->handle_;
4499b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        } else {
4509b92c6b4651e608125a48f8f06a7a840042e090dWink Saville          result = v8::Undefined();
4519b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        }
4523d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Serialize(Arguments&) X");
4539b92c6b4651e608125a48f8f06a7a840042e090dWink Saville        return result;
4543d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
4553d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4563d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      static Handle<Value> ToString(const Arguments& args) {
4573d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return String::New(UnwrapThis<Type>(args)->descriptor_->full_name().c_str());
4583d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
4593d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    };
4603d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4613d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    Message* NewMessage(const Descriptor* descriptor) {
4623d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::NewMessage(descriptor) EX:");
4633d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      return factory_.GetPrototype(descriptor)->New();
4643d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    }
4653d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4663d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    Type* GetType(const Descriptor* descriptor) {
4673d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::GetType(descriptor) E:");
4683d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Type* result = types_[descriptor];
4693d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      if (result) return result;
4703d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4713d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      result = types_[descriptor] =
4723d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        new Type(this, descriptor, TypeTemplate->GetFunction()->NewInstance());
4733d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4743d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      // managed schema->[type] link
4753d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Handle<Array> types = handle_->GetInternalField(1).As<Array>();
4763d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      types->Set(types->Length(), result->handle_);
4773d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::GetType(descriptor) X:");
4783d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      return result;
4793d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    }
4803d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4813d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    const DescriptorPool* pool_;
4823d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    map<const Descriptor*, Type*> types_;
4833d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    DynamicMessageFactory factory_;
4843d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4853d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    static Handle<Value> GetType(const Local<String> name,
4863d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                                 const AccessorInfo& args) {
4873d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::GetType(name, args) E:");
4883d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Schema* schema = UnwrapThis<Schema>(args);
4893d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      const Descriptor* descriptor =
4903d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        schema->pool_->FindMessageTypeByName(*String::AsciiValue(name));
4913d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4923d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::GetType(name, args) X:");
4933d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      return descriptor ?
4943d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        schema->GetType(descriptor)->Constructor() :
4953d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        Handle<Function>();
4963d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    }
4973d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
4983d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    static Handle<Value> NewSchema(const Arguments& args) {
4993d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::NewSchema E: args.Length()=%d", args.Length());
5003d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      if (!args.Length()) {
5013d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return (new Schema(args.This(),
5023d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville                           DescriptorPool::generated_pool()))->handle_;
5033d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
5043d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5053d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      Buffer* buf = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
5063d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5073d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      FileDescriptorSet descriptors;
5083d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      if (!descriptors.ParseFromArray(buf->data(), buf->length())) {
5093d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        DBG("Schema::NewSchema X: bad descriptor");
5103d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        return v8::ThrowException(String::New("Malformed descriptor"));
5113d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
5123d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5133d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DescriptorPool* pool = new DescriptorPool;
5143d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      for (int i = 0; i < descriptors.file_size(); i++) {
5153d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville        pool->BuildFile(descriptors.file(i));
5163d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      }
5173d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5183d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      DBG("Schema::NewSchema X");
5193d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville      return (new Schema(args.This(), pool))->handle_;
5203d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    }
5213d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  };
5223d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5233d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  void Init() {
5243d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    DBG("Init E:");
5253d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    HandleScope handle_scope;
5263d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5273d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    TypeTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New());
5283d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    TypeTemplate->SetClassName(String::New("Type"));
5293d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    // native self
5303d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    // owning schema (so GC can manage our lifecyle)
5313d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    // constructor
5323d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    // toArray
5333d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    TypeTemplate->InstanceTemplate()->SetInternalFieldCount(4);
5343d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5353d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    SchemaTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Schema::NewSchema));
5363d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    SchemaTemplate->SetClassName(String::New("Schema"));
5373d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    // native self
5383d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    // array of types (so GC can manage our lifecyle)
5393d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    SchemaTemplate->InstanceTemplate()->SetInternalFieldCount(2);
5403d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    SchemaTemplate->InstanceTemplate()->SetNamedPropertyHandler(Schema::GetType);
5413d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5423d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    ParseTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Schema::Type::Parse));
5433d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    SerializeTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Schema::Type::Serialize));
5443d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5453d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville    DBG("Init X:");
5463d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  }
5473d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5483d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville}  // namespace protobuf_v8
5493d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville
5503d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Savilleextern "C" void SchemaObjectTemplateInit(Handle<ObjectTemplate> target) {
5513d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  DBG("SchemaObjectTemplateInit(target) EX:");
5523d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville  target->Set(String::New("Schema"), protobuf_v8::SchemaTemplate);
5533d6d348df5378b3f3f79ebbfad21d86ae1c9f239Wink Saville}
554