Commit 55cf8abe authored by Josh Haberman's avatar Josh Haberman

Merge branch 'master' of github.com:google/protobuf

parents cb3caf1e 2cb2358c
......@@ -16,6 +16,7 @@ m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
autom4te.cache
# downloaded files
gtest
......@@ -61,3 +62,13 @@ src/test_plugin
src/testzip.*
src/zcg*zip
ar-lib
test-driver
compile
src/**/*.log
src/**/*.trs
# JavaBuild output.
java/target
javanano/target
[submodule "upb"]
path = upb
url = https://github.com/haberman/upb
language: cpp
script: ./autogen.sh && ./configure && make distcheck
notifications:
email: false
......@@ -195,7 +195,6 @@ python_EXTRA_DIST= \
python/google/protobuf/internal/wire_format.py \
python/google/protobuf/internal/wire_format_test.py \
python/google/protobuf/internal/__init__.py \
python/google/protobuf/internal/import_test_package/BUILD \
python/google/protobuf/internal/import_test_package/__init__.py \
python/google/protobuf/internal/import_test_package/inner.proto \
python/google/protobuf/internal/import_test_package/outer.proto \
......@@ -240,15 +239,26 @@ python_EXTRA_DIST= \
python/README.txt
ruby_EXTRA_DIST= \
ruby/ext/defs.c \
ruby/ext/encode_decode.c \
ruby/ext/extconf.rb \
ruby/ext/message.c \
ruby/ext/protobuf.c \
ruby/ext/protobuf.h \
ruby/ext/repeated_field.c \
ruby/ext/storage.c \
ruby/ext/test.rb
ruby/README.md \
ruby/Rakefile \
ruby/ext/google/protobuf_c/defs.c \
ruby/ext/google/protobuf_c/encode_decode.c \
ruby/ext/google/protobuf_c/extconf.rb \
ruby/ext/google/protobuf_c/map.c \
ruby/ext/google/protobuf_c/message.c \
ruby/ext/google/protobuf_c/protobuf.c \
ruby/ext/google/protobuf_c/protobuf.h \
ruby/ext/google/protobuf_c/repeated_field.c \
ruby/ext/google/protobuf_c/storage.c \
ruby/ext/google/protobuf_c/upb.c \
ruby/ext/google/protobuf_c/upb.h \
ruby/google-protobuf.gemspec \
ruby/lib/google/protobuf.rb \
ruby/tests/basic.rb \
ruby/tests/stress.rb \
ruby/tests/generated_code.proto \
ruby/tests/generated_code.rb \
ruby/tests/generated_code_test.rb
all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
......
Protocol Buffers - Google's data interchange format
===================================================
[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
Copyright 2008 Google Inc.
https://developers.google.com/protocol-buffers/
......
......@@ -15,12 +15,6 @@ __EOF__
exit 1
fi
if test -e .git; then
# pull down git submodules.
git submodule init
git submodule update
fi
# Check that gtest is present. Usually it is already there since the
# directory is set up as an SVN external.
if test ! -e gtest; then
......
......@@ -94,6 +94,7 @@
<arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/map_test.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources" />
......
......@@ -638,4 +638,44 @@ public final class CodedInputByteBufferNano {
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
}
// Read a primitive type.
Object readPrimitiveField(int type) throws IOException {
switch (type) {
case InternalNano.TYPE_DOUBLE:
return readDouble();
case InternalNano.TYPE_FLOAT:
return readFloat();
case InternalNano.TYPE_INT64:
return readInt64();
case InternalNano.TYPE_UINT64:
return readUInt64();
case InternalNano.TYPE_INT32:
return readInt32();
case InternalNano.TYPE_FIXED64:
return readFixed64();
case InternalNano.TYPE_FIXED32:
return readFixed32();
case InternalNano.TYPE_BOOL:
return readBool();
case InternalNano.TYPE_STRING:
return readString();
case InternalNano.TYPE_BYTES:
return readBytes();
case InternalNano.TYPE_UINT32:
return readUInt32();
case InternalNano.TYPE_ENUM:
return readEnum();
case InternalNano.TYPE_SFIXED32:
return readSFixed32();
case InternalNano.TYPE_SFIXED64:
return readSFixed64();
case InternalNano.TYPE_SINT32:
return readSInt32();
case InternalNano.TYPE_SINT64:
return readSInt64();
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
}
......@@ -876,4 +876,128 @@ public final class CodedOutputByteBufferNano {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 63);
}
static int computeFieldSize(int number, int type, Object object) {
switch (type) {
case InternalNano.TYPE_BOOL:
return computeBoolSize(number, (Boolean) object);
case InternalNano.TYPE_BYTES:
return computeBytesSize(number, (byte[]) object);
case InternalNano.TYPE_STRING:
return computeStringSize(number, (String) object);
case InternalNano.TYPE_FLOAT:
return computeFloatSize(number, (Float) object);
case InternalNano.TYPE_DOUBLE:
return computeDoubleSize(number, (Double) object);
case InternalNano.TYPE_ENUM:
return computeEnumSize(number, (Integer) object);
case InternalNano.TYPE_FIXED32:
return computeFixed32Size(number, (Integer) object);
case InternalNano.TYPE_INT32:
return computeInt32Size(number, (Integer) object);
case InternalNano.TYPE_UINT32:
return computeUInt32Size(number, (Integer) object);
case InternalNano.TYPE_SINT32:
return computeSInt32Size(number, (Integer) object);
case InternalNano.TYPE_SFIXED32:
return computeSFixed32Size(number, (Integer) object);
case InternalNano.TYPE_INT64:
return computeInt64Size(number, (Long) object);
case InternalNano.TYPE_UINT64:
return computeUInt64Size(number, (Long) object);
case InternalNano.TYPE_SINT64:
return computeSInt64Size(number, (Long) object);
case InternalNano.TYPE_FIXED64:
return computeFixed64Size(number, (Long) object);
case InternalNano.TYPE_SFIXED64:
return computeSFixed64Size(number, (Long) object);
case InternalNano.TYPE_MESSAGE:
return computeMessageSize(number, (MessageNano) object);
case InternalNano.TYPE_GROUP:
return computeGroupSize(number, (MessageNano) object);
default:
throw new IllegalArgumentException("Unknown type: " + type);
}
}
void writeField(int number, int type, Object value)
throws IOException {
switch (type) {
case InternalNano.TYPE_DOUBLE:
Double doubleValue = (Double) value;
writeDouble(number, doubleValue);
break;
case InternalNano.TYPE_FLOAT:
Float floatValue = (Float) value;
writeFloat(number, floatValue);
break;
case InternalNano.TYPE_INT64:
Long int64Value = (Long) value;
writeInt64(number, int64Value);
break;
case InternalNano.TYPE_UINT64:
Long uint64Value = (Long) value;
writeUInt64(number, uint64Value);
break;
case InternalNano.TYPE_INT32:
Integer int32Value = (Integer) value;
writeInt32(number, int32Value);
break;
case InternalNano.TYPE_FIXED64:
Long fixed64Value = (Long) value;
writeFixed64(number, fixed64Value);
break;
case InternalNano.TYPE_FIXED32:
Integer fixed32Value = (Integer) value;
writeFixed32(number, fixed32Value);
break;
case InternalNano.TYPE_BOOL:
Boolean boolValue = (Boolean) value;
writeBool(number, boolValue);
break;
case InternalNano.TYPE_STRING:
String stringValue = (String) value;
writeString(number, stringValue);
break;
case InternalNano.TYPE_BYTES:
byte[] bytesValue = (byte[]) value;
writeBytes(number, bytesValue);
break;
case InternalNano.TYPE_UINT32:
Integer uint32Value = (Integer) value;
writeUInt32(number, uint32Value);
break;
case InternalNano.TYPE_ENUM:
Integer enumValue = (Integer) value;
writeEnum(number, enumValue);
break;
case InternalNano.TYPE_SFIXED32:
Integer sfixed32Value = (Integer) value;
writeSFixed32(number, sfixed32Value);
break;
case InternalNano.TYPE_SFIXED64:
Long sfixed64Value = (Long) value;
writeSFixed64(number, sfixed64Value);
break;
case InternalNano.TYPE_SINT32:
Integer sint32Value = (Integer) value;
writeSInt32(number, sint32Value);
break;
case InternalNano.TYPE_SINT64:
Long sint64Value = (Long) value;
writeSInt64(number, sint64Value);
break;
case InternalNano.TYPE_MESSAGE:
MessageNano messageValue = (MessageNano) value;
writeMessage(number, messageValue);
break;
case InternalNano.TYPE_GROUP:
MessageNano groupValue = (MessageNano) value;
writeGroup(number, groupValue);
break;
default:
throw new IOException("Unknown type: " + type);
}
}
}
......@@ -55,24 +55,24 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* PrimitiveExtension // for primitive/enum typed extensions
*/
public static final int TYPE_DOUBLE = 1;
public static final int TYPE_FLOAT = 2;
public static final int TYPE_INT64 = 3;
public static final int TYPE_UINT64 = 4;
public static final int TYPE_INT32 = 5;
public static final int TYPE_FIXED64 = 6;
public static final int TYPE_FIXED32 = 7;
public static final int TYPE_BOOL = 8;
public static final int TYPE_STRING = 9;
public static final int TYPE_GROUP = 10;
public static final int TYPE_MESSAGE = 11;
public static final int TYPE_BYTES = 12;
public static final int TYPE_UINT32 = 13;
public static final int TYPE_ENUM = 14;
public static final int TYPE_SFIXED32 = 15;
public static final int TYPE_SFIXED64 = 16;
public static final int TYPE_SINT32 = 17;
public static final int TYPE_SINT64 = 18;
public static final int TYPE_DOUBLE = InternalNano.TYPE_DOUBLE;
public static final int TYPE_FLOAT = InternalNano.TYPE_FLOAT;
public static final int TYPE_INT64 = InternalNano.TYPE_INT64;
public static final int TYPE_UINT64 = InternalNano.TYPE_UINT64;
public static final int TYPE_INT32 = InternalNano.TYPE_INT32;
public static final int TYPE_FIXED64 = InternalNano.TYPE_FIXED64;
public static final int TYPE_FIXED32 = InternalNano.TYPE_FIXED32;
public static final int TYPE_BOOL = InternalNano.TYPE_BOOL;
public static final int TYPE_STRING = InternalNano.TYPE_STRING;
public static final int TYPE_GROUP = InternalNano.TYPE_GROUP;
public static final int TYPE_MESSAGE = InternalNano.TYPE_MESSAGE;
public static final int TYPE_BYTES = InternalNano.TYPE_BYTES;
public static final int TYPE_UINT32 = InternalNano.TYPE_UINT32;
public static final int TYPE_ENUM = InternalNano.TYPE_ENUM;
public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32;
public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64;
public static final int TYPE_SINT32 = InternalNano.TYPE_SINT32;
public static final int TYPE_SINT64 = InternalNano.TYPE_SINT64;
/**
* Creates an {@code Extension} of the given message type and tag number.
......@@ -338,42 +338,7 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
@Override
protected Object readData(CodedInputByteBufferNano input) {
try {
switch (type) {
case TYPE_DOUBLE:
return input.readDouble();
case TYPE_FLOAT:
return input.readFloat();
case TYPE_INT64:
return input.readInt64();
case TYPE_UINT64:
return input.readUInt64();
case TYPE_INT32:
return input.readInt32();
case TYPE_FIXED64:
return input.readFixed64();
case TYPE_FIXED32:
return input.readFixed32();
case TYPE_BOOL:
return input.readBool();
case TYPE_STRING:
return input.readString();
case TYPE_BYTES:
return input.readBytes();
case TYPE_UINT32:
return input.readUInt32();
case TYPE_ENUM:
return input.readEnum();
case TYPE_SFIXED32:
return input.readSFixed32();
case TYPE_SFIXED64:
return input.readSFixed64();
case TYPE_SINT32:
return input.readSInt32();
case TYPE_SINT64:
return input.readSInt64();
default:
throw new IllegalArgumentException("Unknown type " + type);
}
return input.readPrimitiveField(type);
} catch (IOException e) {
throw new IllegalArgumentException("Error reading extension field", e);
}
......
......@@ -30,8 +30,13 @@
package com.google.protobuf.nano;
import com.google.protobuf.nano.MapFactories.MapFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
/**
* The classes contained within are used internally by the Protocol Buffer
......@@ -43,6 +48,26 @@ import java.util.Arrays;
*/
public final class InternalNano {
public static final int TYPE_DOUBLE = 1;
public static final int TYPE_FLOAT = 2;
public static final int TYPE_INT64 = 3;
public static final int TYPE_UINT64 = 4;
public static final int TYPE_INT32 = 5;
public static final int TYPE_FIXED64 = 6;
public static final int TYPE_FIXED32 = 7;
public static final int TYPE_BOOL = 8;
public static final int TYPE_STRING = 9;
public static final int TYPE_GROUP = 10;
public static final int TYPE_MESSAGE = 11;
public static final int TYPE_BYTES = 12;
public static final int TYPE_UINT32 = 13;
public static final int TYPE_ENUM = 14;
public static final int TYPE_SFIXED32 = 15;
public static final int TYPE_SFIXED64 = 16;
public static final int TYPE_SINT32 = 17;
public static final int TYPE_SINT64 = 18;
private InternalNano() {}
/**
......@@ -329,5 +354,203 @@ public final class InternalNano {
}
return result;
}
private static final byte[] EMPTY_BYTES = new byte[0];
private static Object primitiveDefaultValue(int type) {
switch (type) {
case TYPE_BOOL:
return Boolean.FALSE;
case TYPE_BYTES:
return EMPTY_BYTES;
case TYPE_STRING:
return "";
case TYPE_FLOAT:
return Float.valueOf(0);
case TYPE_DOUBLE:
return Double.valueOf(0);
case TYPE_ENUM:
case TYPE_FIXED32:
case TYPE_INT32:
case TYPE_UINT32:
case TYPE_SINT32:
case TYPE_SFIXED32:
return Integer.valueOf(0);
case TYPE_INT64:
case TYPE_UINT64:
case TYPE_SINT64:
case TYPE_FIXED64:
case TYPE_SFIXED64:
return Long.valueOf(0L);
case TYPE_MESSAGE:
case TYPE_GROUP:
default:
throw new IllegalArgumentException(
"Type: " + type + " is not a primitive type.");
}
}
/**
* Merges the map entry into the map field. Note this is only supposed to
* be called by generated messages.
*
* @param map the map field; may be null, in which case a map will be
* instantiated using the {@link MapFactories.MapFactory}
* @param input the input byte buffer
* @param keyType key type, as defined in InternalNano.TYPE_*
* @param valueType value type, as defined in InternalNano.TYPE_*
* @param value an new instance of the value, if the value is a TYPE_MESSAGE;
* otherwise this parameter can be null and will be ignored.
* @param keyTag wire tag for the key
* @param valueTag wire tag for the value
* @return the map field
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static final <K, V> Map<K, V> mergeMapEntry(
CodedInputByteBufferNano input,
Map<K, V> map,
MapFactory mapFactory,
int keyType,
int valueType,
V value,
int keyTag,
int valueTag) throws IOException {
map = mapFactory.forMap(map);
final int length = input.readRawVarint32();
final int oldLimit = input.pushLimit(length);
K key = null;
while (true) {
int tag = input.readTag();
if (tag == 0) {
break;
}
if (tag == keyTag) {
key = (K) input.readPrimitiveField(keyType);
} else if (tag == valueTag) {
if (valueType == TYPE_MESSAGE) {
input.readMessage((MessageNano) value);
} else {
value = (V) input.readPrimitiveField(valueType);
}
} else {
if (!input.skipField(tag)) {
break;
}
}
}
input.checkLastTagWas(0);
input.popLimit(oldLimit);
if (key == null) {
// key can only be primitive types.
key = (K) primitiveDefaultValue(keyType);
}
if (value == null) {
// message type value will be initialized by code-gen.
value = (V) primitiveDefaultValue(valueType);
}
map.put(key, value);
return map;
}
public static <K, V> void serializeMapField(
CodedOutputByteBufferNano output,
Map<K, V> map, int number, int keyType, int valueType)
throws IOException {
for (Entry<K, V> entry: map.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
if (key == null || value == null) {
throw new IllegalStateException(
"keys and values in maps cannot be null");
}
int entrySize =
CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
output.writeRawVarint32(entrySize);
output.writeField(1, keyType, key);
output.writeField(2, valueType, value);
}
}
public static <K, V> int computeMapFieldSize(
Map<K, V> map, int number, int keyType, int valueType) {
int size = 0;
int tagSize = CodedOutputByteBufferNano.computeTagSize(number);
for (Entry<K, V> entry: map.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
if (key == null || value == null) {
throw new IllegalStateException(
"keys and values in maps cannot be null");
}
int entrySize =
CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
size += tagSize + entrySize
+ CodedOutputByteBufferNano.computeRawVarint32Size(entrySize);
}
return size;
}
/**
* Checks whether two {@link Map} are equal. We don't use the default equals
* method of {@link Map} because it compares by identity not by content for
* byte arrays.
*/
public static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
if (a == b) {
return true;
}
if (a == null) {
return b.size() == 0;
}
if (b == null) {
return a.size() == 0;
}
if (a.size() != b.size()) {
return false;
}
for (Entry<K, V> entry : a.entrySet()) {
if (!b.containsKey(entry.getKey())) {
return false;
}
if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) {
return false;
}
}
return true;
}
private static boolean equalsMapValue(Object a, Object b) {
if (a == null || b == null) {
throw new IllegalStateException(
"keys and values in maps cannot be null");
}
if (a instanceof byte[] && b instanceof byte[]) {
return Arrays.equals((byte[]) a, (byte[]) b);
}
return a.equals(b);
}
public static <K, V> int hashCode(Map<K, V> map) {
if (map == null) {
return 0;
}
int result = 0;
for (Entry<K, V> entry : map.entrySet()) {
result += hashCodeForMap(entry.getKey())
^ hashCodeForMap(entry.getValue());
}
return result;
}
private static int hashCodeForMap(Object o) {
if (o instanceof byte[]) {
return Arrays.hashCode((byte[]) o);
}
return o.hashCode();
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2013 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf.nano;
import java.util.HashMap;
import java.util.Map;
/**
* Utility class for maps support.
*/
public final class MapFactories {
public static interface MapFactory {
<K, V> Map<K, V> forMap(Map<K, V> oldMap);
}
// NOTE(liujisi): The factory setter is temporarily marked as package private.
// The way to provide customized implementations of maps for different
// platforms are still under discussion. Mark it as private to avoid exposing
// the API in proto3 alpha release.
/* public */ static void setMapFactory(MapFactory newMapFactory) {
mapFactory = newMapFactory;
}
public static MapFactory getMapFactory() {
return mapFactory;
}
private static class DefaultMapFactory implements MapFactory {
public <K, V> Map<K, V> forMap(Map<K, V> oldMap) {
if (oldMap == null) {
return new HashMap<K, V>();
}
return oldMap;
}
}
private static volatile MapFactory mapFactory = new DefaultMapFactory();
private MapFactories() {}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package map_test;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "MapTestProto";
message TestMap {
message MessageValue {
int32 value = 1;
int32 value2 = 2;
}
enum EnumValue {
FOO = 0;
BAR = 1;
BAZ = 2;
QUX = 3;
}
map<int32, int32> int32_to_int32_field = 1;
map<int32, string> int32_to_string_field = 2;
map<int32, bytes> int32_to_bytes_field = 3;
map<int32, EnumValue> int32_to_enum_field = 4;
map<int32, MessageValue> int32_to_message_field = 5;
map<string, int32> string_to_int32_field = 6;
map<bool, bool> bool_to_bool_field = 7;
// Test all the other primitive types. As the key and value are not coupled in
// the implementation, we do not test all the combinations of key/value pairs,
// so that we can keep the number of test cases manageable
map<uint32, uint32> uint32_to_uint32_field = 11;
map<sint32, sint32> sint32_to_sint32_field = 12;
map<fixed32, fixed32> fixed32_to_fixed32_field = 13;
map<sfixed32, sfixed32> sfixed32_to_sfixed32_field = 14;
map<int64, int64> int64_to_int64_field = 15;
map<uint64, uint64> uint64_to_uint64_field = 16;
map<sint64, sint64> sint64_to_sint64_field = 17;
map<fixed64, fixed64> fixed64_to_fixed64_field = 18;
map<sfixed64, sfixed64> sfixed64_to_sfixed64_field = 19;
}
......@@ -26,7 +26,7 @@ join the Protocol Buffers discussion list and let us know!
Installation
============
1) Make sure you have Python 2.4 or newer. If in doubt, run:
1) Make sure you have Python 2.6 or newer. If in doubt, run:
$ python -V
......@@ -35,7 +35,7 @@ Installation
If you would rather install it manually, you may do so by following
the instructions on this page:
http://peak.telecommunity.com/DevCenter/EasyInstall#installation-instructions
https://packaging.python.org/en/latest/installing.html#setup-for-installing-packages
3) Build the C++ code, or install a binary distribution of protoc. If
you install a binary distribution, make sure that it is the same
......
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
# https://developers.google.com/protocol-buffers/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Needs to stay compatible with Python 2.5 due to GAE.
#
# Copyright 2007 Google Inc. All Rights Reserved.
__version__ = '3.0.0-pre'
# Description:
# An example package that contains nested protos that are imported from
# __init__.py. See testPackageInitializationImport in reflection_test.py for
# details.
package(
default_visibility = ["//net/proto2/python/internal:__pkg__"],
)
proto_library(
name = "inner_proto",
srcs = ["inner.proto"],
py_api_version = 2,
)
proto_library(
name = "outer_proto",
srcs = ["outer.proto"],
py_api_version = 2,
deps = [":inner_proto"],
)
py_library(
name = "import_test_package",
srcs = ["__init__.py"],
deps = [":outer_proto"],
)
......@@ -18,13 +18,7 @@ To build this Ruby extension, you will need:
* a C compiler
* the upb submodule
First, ensure that upb/ is checked out:
$ cd .. # top level protobuf directory
$ git submodule init
$ git submodule update
Then install the required Ruby gems:
First, install the required Ruby gems:
$ sudo gem install bundler rake rake-compiler rspec rubygems-tasks
......@@ -32,3 +26,7 @@ Then build the Gem:
$ rake gem
$ gem install pkg/protobuf-$VERSION.gem
This gem includes the upb parsing and serialization library as a single-file
amalgamation. It is up-to-date with upb git commit
`535bc2fe2f2b467f59347ffc9449e11e47791257`.
require "rake/extensiontask"
require "rake/testtask"
spec = Gem::Specification.new do |s|
s.name = "protobuf"
s.version = "2.6.2"
s.licenses = ["BSD"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
s.authors = ["Protobuf Authors"]
s.email = "protobuf@googlegroups.com"
s.files = ["lib/protobuf_c.so", "lib/protobuf.rb"]
end
spec = Gem::Specification.load("google-protobuf.gemspec")
Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
ext.lib_dir = "lib"
ext.config_script = "extconf.rb"
ext.ext_dir = "ext/google/protobuf_c"
ext.lib_dir = "lib/google"
end
Rake::TestTask.new(:test => :build) do |t|
t.test_files = FileList["tests/*.rb"]
end
task :chmod do
File.chmod(0755, "lib/protobuf_c.so")
end
Gem::PackageTask.new(spec) do |pkg|
end
task :package => :chmod
task :gem => :chmod
task :build => [:clean, :compile]
task :default => [:build]
......
#!/usr/bin/ruby
require 'mkmf'
$CFLAGS += " -O3 -std=c99 -Wno-unused-function -DNDEBUG "
$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
"repeated_field.o", "map.o", "encode_decode.o", "upb.o"]
create_makefile("google/protobuf_c")
This diff is collapsed.
......@@ -70,6 +70,35 @@ VALUE Message_alloc(VALUE klass) {
return ret;
}
static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
// If no fields in the oneof, always nil.
if (upb_oneofdef_numfields(o) == 0) {
return Qnil;
}
// Grab the first field in the oneof so we can get its layout info to find the
// oneof_case field.
upb_oneof_iter it;
upb_oneof_begin(&it, o);
assert(!upb_oneof_done(&it));
const upb_fielddef* first_field = upb_oneof_iter_field(&it);
assert(upb_fielddef_containingoneof(first_field) != NULL);
size_t case_ofs =
self->descriptor->layout->
fields[upb_fielddef_index(first_field)].case_offset;
uint32_t oneof_case = *((uint32_t*)(Message_data(self) + case_ofs));
if (oneof_case == ONEOF_CASE_NONE) {
return Qnil;
}
// oneof_case is a field index, so find that field.
const upb_fielddef* f = upb_oneofdef_itof(o, oneof_case);
assert(f != NULL);
return ID2SYM(rb_intern(upb_fielddef_name(f)));
}
/*
* call-seq:
* Message.method_missing(*args)
......@@ -82,6 +111,10 @@ VALUE Message_alloc(VALUE klass) {
*
* msg.foo = 42
* puts msg.foo
*
* This method also provides read-only accessors for oneofs. If a oneof exists
* with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
* the name of the field in that oneof that is currently set, or nil if none.
*/
VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
MessageHeader* self;
......@@ -104,6 +137,17 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
name_len--;
}
// Check for a oneof name first.
const upb_oneofdef* o = upb_msgdef_ntoo(self->descriptor->msgdef,
name, name_len);
if (o != NULL) {
if (setter) {
rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
}
return which_oneof_field(self, o);
}
// Otherwise, check for a field with that name.
const upb_fielddef* f = upb_msgdef_ntof(self->descriptor->msgdef,
name, name_len);
......@@ -139,7 +183,14 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
"Unknown field name in initialization map entry.");
}
if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
if (is_map_field(f)) {
if (TYPE(val) != T_HASH) {
rb_raise(rb_eArgError,
"Expected Hash object as initializer value for map field.");
}
VALUE map = layout_get(self->descriptor->layout, Message_data(self), f);
Map_merge_into_self(map, val);
} else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
if (TYPE(val) != T_ARRAY) {
rb_raise(rb_eArgError,
"Expected array as initializer value for repeated field.");
......@@ -450,13 +501,15 @@ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
* call-seq:
* Google::Protobuf.deep_copy(obj) => copy_of_obj
*
* Performs a deep copy of either a RepeatedField instance or a message object,
* recursively copying its members.
* Performs a deep copy of a RepeatedField instance, a Map instance, or a
* message object, recursively copying its members.
*/
VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
VALUE klass = CLASS_OF(obj);
if (klass == cRepeatedField) {
return RepeatedField_deep_copy(obj);
} else if (klass == cMap) {
return Map_deep_copy(obj);
} else {
return Message_deep_copy(obj);
}
......
......@@ -77,11 +77,14 @@ void Init_protobuf_c() {
DescriptorPool_register(protobuf);
Descriptor_register(protobuf);
FieldDescriptor_register(protobuf);
OneofDescriptor_register(protobuf);
EnumDescriptor_register(protobuf);
MessageBuilderContext_register(internal);
OneofBuilderContext_register(internal);
EnumBuilderContext_register(internal);
Builder_register(internal);
RepeatedField_register(protobuf);
Map_register(protobuf);
rb_define_singleton_method(protobuf, "encode", Google_Protobuf_encode, 1);
rb_define_singleton_method(protobuf, "decode", Google_Protobuf_decode, 2);
......
......@@ -316,6 +316,29 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
return new_rptfield;
}
/*
* call-seq:
* RepeatedField.to_ary => array
*
* Used when converted implicitly into array, e.g. compared to an Array.
* Also called as a fallback of Object#to_a
*/
VALUE RepeatedField_to_ary(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
upb_fieldtype_t field_type = self->field_type;
size_t elem_size = native_slot_size(field_type);
size_t off = 0;
VALUE ary = rb_ary_new2(self->size);
for (int i = 0; i < self->size; i++, off += elem_size) {
void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
rb_ary_push(ary, elem);
}
return ary;
}
/*
* call-seq:
* RepeatedField.==(other) => boolean
......@@ -324,6 +347,10 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
* element types are equal, their lengths are equal, and each element is equal.
* Elements are compared as per normal Ruby semantics, by calling their :==
* methods (or performing a more efficient comparison for primitive types).
*
* Repeated fields with dissimilar element types are never equal, even if value
* comparison (for example, between integers and floats) would have otherwise
* indicated that every element has equal value.
*/
VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
if (_self == _other) {
......@@ -331,15 +358,9 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
}
RepeatedField* self = ruby_to_RepeatedField(_self);
// Inefficient but workable: to support comparison to a generic array, we
// build a temporary RepeatedField of our type.
if (TYPE(_other) == T_ARRAY) {
VALUE new_rptfield = RepeatedField_new_this_type(_self);
for (int i = 0; i < RARRAY_LEN(_other); i++) {
VALUE elem = rb_ary_entry(_other, i);
RepeatedField_push(new_rptfield, elem);
}
_other = new_rptfield;
VALUE self_ary = RepeatedField_to_ary(_self);
return rb_equal(self_ary, _other);
}
RepeatedField* other = ruby_to_RepeatedField(_other);
......@@ -397,29 +418,8 @@ VALUE RepeatedField_hash(VALUE _self) {
* representation computed by its own #inspect method.
*/
VALUE RepeatedField_inspect(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
VALUE str = rb_str_new2("[");
bool first = true;
upb_fieldtype_t field_type = self->field_type;
VALUE field_type_class = self->field_type_class;
size_t elem_size = native_slot_size(field_type);
size_t off = 0;
for (int i = 0; i < self->size; i++, off += elem_size) {
void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, field_type_class, mem);
if (!first) {
str = rb_str_cat2(str, ", ");
} else {
first = false;
}
str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
}
str = rb_str_cat2(str, "]");
return str;
VALUE self_ary = RepeatedField_to_ary(_self);
return rb_funcall(self_ary, rb_intern("inspect"), 0);
}
/*
......@@ -458,7 +458,7 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
return dupped;
}
static void validate_type_class(upb_fieldtype_t type, VALUE klass) {
void validate_type_class(upb_fieldtype_t type, VALUE klass) {
if (rb_iv_get(klass, kDescriptorInstanceVar) == Qnil) {
rb_raise(rb_eArgError,
"Type class has no descriptor. Please pass a "
......@@ -590,6 +590,7 @@ void RepeatedField_register(VALUE module) {
// Also define #clone so that we don't inherit Object#clone.
rb_define_method(klass, "clone", RepeatedField_dup, 0);
rb_define_method(klass, "==", RepeatedField_eq, 1);
rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
rb_define_method(klass, "hash", RepeatedField_hash, 0);
rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
rb_define_method(klass, "+", RepeatedField_plus, 1);
......
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/ruby
require 'mkmf'
upb_path = File.absolute_path(File.dirname($0)) + "/../../../upb"
libs = ["upb_pic", "upb.pb_pic", "upb.json_pic"]
system("cd #{upb_path}; make " + libs.map{|l| "lib/lib#{l}.a"}.join(" "))
$CFLAGS += " -O3 -std=c99 -Wno-unused-function -DNDEBUG"
find_header("upb/upb.h", upb_path) or
raise "Can't find upb headers"
find_library("upb_pic", "upb_msgdef_new", upb_path + "/lib") or
raise "Can't find upb lib"
find_library("upb.pb_pic", "upb_pbdecoder_init", upb_path + "/lib") or
raise "Can't find upb.pb lib"
find_library("upb.json_pic", "upb_json_printer_init", upb_path + "/lib") or
raise "Can't find upb.pb lib"
$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
"repeated_field.o", "encode_decode.o"]
create_makefile("protobuf_c")
class << Gem::Specification
def find_c_source(dir)
`cd #{dir}; git ls-files "*.c" "*.h" extconf.rb Makefile`.split
.map{|f| "#{dir}/#{f}"}
end
end
Gem::Specification.new do |s|
s.name = "google-protobuf"
s.version = "3.0.0.alpha.2"
s.licenses = ["BSD"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
s.authors = ["Protobuf Authors"]
s.email = "protobuf@googlegroups.com"
s.require_paths = ["lib"]
s.extensions = ["ext/google/protobuf_c/extconf.rb"]
s.files = ["lib/google/protobuf.rb"] +
# extension C source
find_c_source("ext/google/protobuf_c")
s.test_files = ["tests/basic.rb",
"tests/stress.rb",
"tests/generated_code_test.rb"]
end
......@@ -28,4 +28,4 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'protobuf_c'
require 'google/protobuf_c'
This diff is collapsed.
syntax = "proto3";
package A.B.C;
message TestMessage {
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional bool optional_bool = 5;
optional double optional_double = 6;
optional float optional_float = 7;
optional string optional_string = 8;
optional bytes optional_bytes = 9;
optional TestEnum optional_enum = 10;
optional TestMessage optional_msg = 11;
repeated int32 repeated_int32 = 21;
repeated int64 repeated_int64 = 22;
repeated uint32 repeated_uint32 = 23;
repeated uint64 repeated_uint64 = 24;
repeated bool repeated_bool = 25;
repeated double repeated_double = 26;
repeated float repeated_float = 27;
repeated string repeated_string = 28;
repeated bytes repeated_bytes = 29;
repeated TestEnum repeated_enum = 30;
repeated TestMessage repeated_msg = 31;
oneof my_oneof {
int32 oneof_int32 = 41;
int64 oneof_int64 = 42;
uint32 oneof_uint32 = 43;
uint64 oneof_uint64 = 44;
bool oneof_bool = 45;
double oneof_double = 46;
float oneof_float = 47;
string oneof_string = 48;
bytes oneof_bytes = 49;
TestEnum oneof_enum = 50;
TestMessage oneof_msg = 51;
}
map<int32, string> map_int32_string = 61;
map<int64, string> map_int64_string = 62;
map<uint32, string> map_uint32_string = 63;
map<uint64, string> map_uint64_string = 64;
map<bool, string> map_bool_string = 65;
map<string, string> map_string_string = 66;
map<string, TestMessage> map_string_msg = 67;
map<string, TestEnum> map_string_enum = 68;
map<string, int32> map_string_int32 = 69;
map<string, bool> map_string_bool = 70;
message NestedMessage {
optional int32 foo = 1;
}
optional NestedMessage nested_message = 80;
}
enum TestEnum {
Default = 0;
A = 1;
B = 2;
C = 3;
}
This diff is collapsed.
#!/usr/bin/ruby
# generated_code.rb is in the same directory as this test.
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
require 'generated_code'
require 'test/unit'
class GeneratedCodeTest < Test::Unit::TestCase
def test_generated_msg
# just test that we can instantiate the message. The purpose of this test
# is to ensure that the output of the code generator is valid Ruby and
# successfully creates message definitions and classes, not to test every
# aspect of the extension (basic.rb is for that).
m = A::B::C::TestMessage.new()
end
end
#!/usr/bin/ruby
require 'protobuf'
require 'google/protobuf'
require 'test/unit'
module StressTest
......
This diff is collapsed.
......@@ -301,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
printer->Print(vars_,
" default:\n"
" GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
" return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n"
" return *static_cast< ::google::protobuf::Message*>(NULL);\n"
" }\n"
"}\n"
"\n");
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -40,7 +40,8 @@ namespace protobuf {
namespace compiler {
namespace ruby {
class Generator : public google::protobuf::compiler::CodeGenerator {
class LIBPROTOC_EXPORT Generator
: public google::protobuf::compiler::CodeGenerator {
virtual bool Generate(
const FileDescriptor* file,
const string& parameter,
......
This diff is collapsed.
This diff is collapsed.
Subproject commit 56913be6bb57f81dbbf7baf9cc9a0a2cd1a36493
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment