Merge branch 'master' into rubybuilder
diff --git a/.gitignore b/.gitignore
index d38133b..4e52414 100644
--- a/.gitignore
+++ b/.gitignore
@@ -183,7 +183,6 @@
 /bazel-*
 
 # ruby test output
-ruby/lib/
 ruby/tests/basic_test_pb.rb
 ruby/tests/basic_test_proto2_pb.rb
 ruby/tests/generated_code_pb.rb
diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c
index 992f54b..88da610 100644
--- a/ruby/ext/google/protobuf_c/defs.c
+++ b/ruby/ext/google/protobuf_c/defs.c
@@ -320,6 +320,29 @@
 
 /*
  * call-seq:
+ *     DescriptorPool.build_file(serialized_file_proto)
+ *
+ * Adds the given serialized FileDescriptorProto to the pool.
+ */
+VALUE DescriptorPool_build(value _self, VALUE serialized_file_proto) {
+  DEFINE_SELF(DescriptorPool, self, _self);
+  Check_Type(serialized_file_proto, T_STRING);
+  upb_arena *arena = upb_arena_new();
+  google_protobuf_FileDescriptorProto* file_proto =
+      google_protobuf_FileDescriptorProto_parse(
+          RSTRING_PTR(serialized_file_proto),
+          RSTRING_LEN(serialized_file_proto), arena);
+  upb_status status;
+  upb_status_clear(&status);
+  if (!upb_symtab_addfile(self->symtab, file_proto, &status)) {
+    rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s",
+             upb_status_errmsg(&status));
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
  *     DescriptorPool.lookup(name) => descriptor
  *
  * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
@@ -1460,6 +1483,11 @@
   return Qnil;
 }
 
+<<<<<<< HEAD
+static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
+                           const VALUE* argv) {
+  DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder);
+=======
 static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self);
 
 /*
@@ -1793,6 +1821,7 @@
 #endif
   MessageBuilderContext* message_builder =
       ruby_to_MessageBuilderContext(_message_builder);
+>>>>>>> master
   VALUE type_class = rb_ary_entry(types, 2);
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(message_builder->file_builder);
diff --git a/ruby/lib/google/protobuf/descriptor_builder.rb b/ruby/lib/google/protobuf/descriptor_builder.rb
new file mode 100644
index 0000000..af485bd
--- /dev/null
+++ b/ruby/lib/google/protobuf/descriptor_builder.rb
@@ -0,0 +1,110 @@
+#!/usr/bin/ruby
+#
+# Summary description of library or script.
+#
+# This doc string should contain an overall description of the module/script
+# and can optionally briefly describe exported classes and functions.
+#
+#    ClassFoo:      One line summary.
+#    function_foo:  One line summary.
+#
+# $Id$
+
+module Google
+  module Protobuf
+    module Internal
+
+      class FileBuilder
+        def initialize(pool, name, options=nil)
+          @pool = pool
+          @file_proto = Google::Protobuf::FileDescriptorProto.new
+          @file_proto.name = name
+          @file_proto.syntax = "proto3"  # Default syntax for Ruby is proto3.
+
+          if options
+            if options.key?(:syntax)
+              @file_proto.syntax = options[:key].to_s
+            end
+          end
+        end
+
+        def add_message(name, &block)
+          MessageBuilder.new(name, @file_proto).instance_eval &block
+        end
+
+        def add_enum(name, &block)
+          enum_proto = Google::Protobuf::
+          EnumBuilder.new(name, @file_proto).instance_eval &block
+        end
+      end
+
+      class MessageBuilder
+        def initialize(name, file_proto)
+          @msg_proto = Google::Protobuf::DescriptorProto.new
+          @msg_proto.name = name
+          file_proto.message_type << @msg_proto
+        end
+
+        def optional(name, type, number, type_class=nil, options=nil)
+          # Allow passing either:
+          # - (name, type, number, options) or
+          # - (name, type, number, type_class, options)
+          if options.nil? and type_class.instance_of?(Hash)
+            options = type_class;
+            type_class = Qnil;
+          end
+          add_field(:LABEL_OPTIONAL, name, type, number, type_class, options)
+        end
+
+        def required(name, type, number, type_class=nil, options=nil)
+          # Allow passing either:
+          # - (name, type, number, options) or
+          # - (name, type, number, type_class, options)
+          if options.nil? and type_class.instance_of?(Hash)
+            options = type_class;
+            type_class = Qnil;
+          end
+          add_field(:LABEL_REQUIRED, name, type, number, type_class, options)
+        end
+
+        def repeated(name, type, number, type_class = nil)
+          add_field(:LABEL_REPEATED, name, type, number, type_class, nil)
+        end
+
+        def map(name, key_type, value_type, number, value_type_class = nil)
+          entry_name = "MapEntry_#{name}"
+          add_message
+        end
+
+        private def add_field(label, name, type, number, type_class, options,
+                              oneof_index)
+          field_proto = Google::Protobuf::FieldDescriptorProto.new(
+            :label => label,
+            :name => name,
+            :type => type,
+            :number => number
+          )
+
+          if type_class
+            # Make it an absolute type name by prepending a dot.
+            field_proto.type_name = "." + type_class
+          end
+
+          if oneof_index
+            field_proto.oneof_index = oneof_index
+          end
+
+          if options
+            if options.key?(:default)
+              # Call #to_s since all defaults are strings in the descriptor.
+              field_proto.default_value = options[:default].to_s
+            end
+          end
+
+          @msg_proto.field << field_proto
+        end
+      end
+
+    end
+  end
+end