Commit 39b30087 authored by Max Cai's avatar Max Cai

Merge remote-tracking branch 'goog/klp-dev-plus-aosp' into tomerge

parents 171633db 941bc6e8
......@@ -93,8 +93,9 @@ Micro version
The runtime and generated code for MICRO_RUNTIME is smaller
because it does not include support for the descriptor and
reflection, and enums are generated as integer constants in
the parent message or the file's outer class. Also, not
currently supported are packed repeated elements or
the parent message or the file's outer class, with no
protection against invalid values set to enum fields. Also,
not currently supported are packed repeated elements or
extensions.
To create a jar file for the runtime and run tests invoke
......@@ -409,11 +410,20 @@ Nano version
============================
Nano is even smaller than micro, especially in the number of generated
functions. It is like micro except:
functions. It is like micro:
- No setter/getter/hazzer functions.
- Has state is not available. Outputs all fields not equal to their
default. (See important implications below.)
- No support for descriptors and reflection;
- Enum constants are integers with no protection against invalid
values set to enum fields.
Except:
- Setter/getter/hazzer/clearer functions are opt-in.
- If not opted in, has state is not available. Serialization outputs
all fields not equal to their default. (See important implications
below.)
- Enum constants can be generated into container interfaces bearing
the enum's name (so the referencing code is in Java style).
- CodedInputStreamMicro is renamed to CodedInputByteBufferNano and can
only take byte[] (not InputStream).
- Similar rename from CodedOutputStreamMicro to
......@@ -426,7 +436,7 @@ functions. It is like micro except:
MessageNano.
- "bytes" are of java type byte[].
IMPORTANT: If you have fields with defaults
IMPORTANT: If you have fields with defaults and opt out of accessors
How fields with defaults are serialized has changed. Because we don't
keep "has" state, any field equal to its default is assumed to be not
......@@ -435,7 +445,8 @@ change the default value of a field. Senders compiled against an older
version of the proto continue to match against the old default, and
don't send values to the receiver even though the receiver assumes the
new default value. Therefore, think carefully about the implications
of changing the default value.
of changing the default value. Alternatively, turn on accessors and
enjoy the benefit of the explicit has() checks.
IMPORTANT: If you have "bytes" fields with non-empty defaults
......@@ -451,7 +462,9 @@ Nano Generator options
java_package -> <file-name>|<package-name>
java_outer_classname -> <file-name>|<package-name>
java_multiple_files -> true or false
java_nano_generate_has -> true or false
java_nano_generate_has -> true or false [DEPRECATED]
optional_field_style -> default or accessors
enum_style -> c or java
java_package:
java_outer_classname:
......@@ -459,6 +472,8 @@ java_multiple_files:
Same as Micro version.
java_nano_generate_has={true,false} (default: false)
DEPRECATED. Use optional_field_style=accessors.
If true, generates a public boolean variable has<fieldname>
accompanying each optional or required field (not present for
repeated fields, groups or messages). It is set to false initially
......@@ -473,7 +488,114 @@ java_nano_generate_has={true,false} (default: false)
many cases reading the default works and determining whether the
field was received over the wire is irrelevant.
To use nano protobufs:
optional_field_style={default,accessors,reftypes} (default: default)
Defines the style of the generated code for fields.
* default *
In the default style, optional fields translate into public mutable
Java fields, and the serialization process is as discussed in the
"IMPORTANT" section above.
* accessors *
When set to 'accessors', each optional field is encapsulated behind
4 accessors, namely get<fieldname>(), set<fieldname>(), has<fieldname>()
and clear<fieldname>() methods, with the standard semantics. The hazzer's
return value determines whether a field is serialized, so this style is
useful when you need to serialize a field with the default value, or check
if a field has been explicitly set to its default value from the wire.
In the 'accessors' style, required fields are still translated to one
public mutable Java field each, and repeated fields are still translated
to arrays. No accessors are generated for them.
IMPORTANT: When using the 'accessors' style, ProGuard should always
be enabled with optimization (don't use -dontoptimize) and allowing
access modification (use -allowaccessmodification). This removes the
unused accessors and maybe inline the rest at the call sites,
reducing the final code size.
TODO(maxtroy): find ProGuard config that would work the best.
* reftypes *
When set to 'reftypes', each proto field is generated as a public Java
field. For primitive types, these fields use the Java reference types
such as java.lang.Integer instead of primitive types such as int.
In the 'reftypes' style, fields are initialized to null (or empty
arrays for repeated fields), and their default values are not available.
They are serialized over the wire based on equality to null.
The 'reftypes' mode has some additional cost due to autoboxing and usage
of reference types. In practice, many boxed types are cached, and so don't
result in object creation. However, references do take slightly more memory
than primitives.
The 'reftypes' mode is useful when you want to be able to serialize fields
with default values, or check if a field has been explicitly set to the
default over the wire without paying the extra method cost of the
'accessors' mode.
Note that if you attempt to write null to a required field in the reftypes
mode, serialization of the proto will cause a NullPointerException. This is
an intentional indicator that you must set required fields.
NOTE
optional_field_style=accessors or reftypes cannot be used together with
java_nano_generate_has=true. If you need the 'has' flag for any
required field (you have no reason to), you can only use
java_nano_generate_has=true.
enum_style={c,java} (default: c)
Defines where to put the int constants generated from enum members.
* c *
Use C-style, so the enum constants are available at the scope where
the enum is defined. A file-scope enum's members are referenced like
'FileOuterClass.ENUM_VALUE'; a message-scope enum's members are
referenced as 'Message.ENUM_VALUE'. The enum name is unavailable.
This complies with the Micro code generator's behavior.
* java *
Use Java-style, so the enum constants are available under the enum
name and referenced like 'EnumName.ENUM_VALUE' (they are still int
constants). The enum name becomes the name of a public interface, at
the scope where the enum is defined. If the enum is file-scope and
the java_multiple_files option is on, the interface will be defined
in its own file. To reduce code size, this interface should not be
implemented and ProGuard shrinking should be used, so after the Java
compiler inlines all referenced enum constants into the call sites,
the interface remains unused and can be removed by ProGuard.
To use nano protobufs within the Android repo:
- Set 'LOCAL_PROTOC_OPTIMIZE_TYPE := nano' in your local .mk file.
When building a Java library or an app (package) target, the build
system will add the Java nano runtime library to the
LOCAL_STATIC_JAVA_LIBRARIES variable, so you don't need to.
- Set 'LOCAL_PROTO_JAVA_OUTPUT_PARAMS := ...' in your local .mk file
for any command-line options you need. Use commas to join multiple
options. Write all options on the same line; avoid backslash-newline
or '+=', because they will introduce spaces in the middle of your
options and the generator is not prepared to handle them.
- The options will be applied to *all* proto files in LOCAL_SRC_FILES
when you build a Java library or package. In case different options
are needed for different proto files, build separate Java libraries
and reference them in your main target. Note: you should make sure
that, for each separate target, all proto files imported from any
proto file in LOCAL_SRC_FILES are included in LOCAL_SRC_FILES. This
is because the generator has to assume that the imported files are
built using the same options, and will generate code that reference
the fields and enums from the imported files using the same code
style.
- Hint: 'include $(CLEAR_VARS)' resets all LOCAL_ variables, including
the two above.
To use nano protobufs outside of Android repo:
- Link with the generated jar file
<protobuf-root>java/target/protobuf-java-2.3.0-nano.jar.
......@@ -484,6 +606,7 @@ java_package=src/proto/simple-data.proto|my_package,\
java_outer_classname=src/proto/simple-data.proto|OuterName:\
.' src/proto/simple-data.proto
Contributing to nano:
Please add/edit tests in NanoTest.java.
......
......@@ -119,6 +119,9 @@ public final class WireFormatNano {
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
* option is on.
*
* <p>Note that the tag might be a end-group tag (rather than the start of an unknown field) in
* which case we do not want to add an unknown field entry.
*
* @param data a Collection in which to store the data.
* @param input the input buffer.
* @param tag the tag of the field.
......@@ -130,11 +133,13 @@ public final class WireFormatNano {
final CodedInputByteBufferNano input,
final int tag) throws IOException {
int startPos = input.getPosition();
boolean skip = input.skipField(tag);
if (!input.skipField(tag)) {
return false; // This wasn't an unknown field, it's an end-group tag.
}
int endPos = input.getPosition();
byte[] bytes = input.getData(startPos, endPos - startPos);
data.add(new UnknownFieldData(tag, bytes));
return skip;
return true;
}
/**
......
......@@ -68,25 +68,40 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Params& par
EnumGenerator::~EnumGenerator() {}
void EnumGenerator::Generate(io::Printer* printer) {
printer->Print("// enum $classname$\n", "classname", descriptor_->name());
for (int i = 0; i < canonical_values_.size(); i++) {
map<string, string> vars;
vars["name"] = RenameJavaKeywords(canonical_values_[i]->name());
vars["canonical_value"] = SimpleItoa(canonical_values_[i]->number());
printer->Print(vars,
"public static final int $name$ = $canonical_value$;\n");
printer->Print(
"// enum $classname$\n",
"classname", descriptor_->name());
// Start of container interface
bool use_shell_class = params_.java_enum_style();
if (use_shell_class) {
printer->Print(
"public interface $classname$ {\n",
"classname", RenameJavaKeywords(descriptor_->name()));
printer->Indent();
}
// -----------------------------------------------------------------
// Canonical values
for (int i = 0; i < canonical_values_.size(); i++) {
printer->Print(
"public static final int $name$ = $canonical_value$;\n",
"name", RenameJavaKeywords(canonical_values_[i]->name()),
"canonical_value", SimpleItoa(canonical_values_[i]->number()));
}
// Aliases
for (int i = 0; i < aliases_.size(); i++) {
map<string, string> vars;
vars["name"] = RenameJavaKeywords(aliases_[i].value->name());
vars["canonical_name"] = aliases_[i].canonical_value->name();
printer->Print(vars,
"public static final int $name$ = $canonical_name$;\n");
printer->Print(
"public static final int $name$ = $canonical_name$;\n",
"name", RenameJavaKeywords(aliases_[i].value->name()),
"canonical_name", RenameJavaKeywords(aliases_[i].canonical_value->name()));
}
// End of container interface
if (use_shell_class) {
printer->Outdent();
printer->Print("}\n");
}
printer->Print("\n");
}
......
......@@ -58,8 +58,16 @@ void SetEnumVariables(const Params& params,
(*variables)["capitalized_name"] =
RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = "int";
(*variables)["default"] = DefaultValue(params, descriptor);
if (params.use_reference_types_for_primitives()
&& !descriptor->is_repeated()) {
(*variables)["type"] = "java.lang.Integer";
(*variables)["default"] = "null";
} else {
(*variables)["type"] = "int";
(*variables)["default"] = DefaultValue(params, descriptor);
}
(*variables)["repeated_default"] =
"com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY";
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
......@@ -81,7 +89,7 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"public int $name$ = $default$;\n");
"public $type$ $name$ = $default$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
......@@ -90,7 +98,18 @@ GenerateMembers(io::Printer* printer) const {
}
void EnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $default$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"has$capitalized_name$ = false;\n");
}
}
void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
" this.$name$ = input.readInt32();\n");
......@@ -146,6 +165,71 @@ string EnumFieldGenerator::GetBoxedType() const {
// ===================================================================
AccessorEnumFieldGenerator::
AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
const Params& params, int has_bit_index)
: FieldGenerator(params), descriptor_(descriptor) {
SetEnumVariables(params, descriptor, &variables_);
SetBitOperationVariables("has", has_bit_index, &variables_);
}
AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private int $name$_ = $default$;\n"
"public int get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
"public void set$capitalized_name$(int value) {\n"
" $name$_ = value;\n"
" $set_has$;\n"
"}\n"
"public boolean has$capitalized_name$() {\n"
" return $get_has$;\n"
"}\n"
"public void clear$capitalized_name$() {\n"
" $name$_ = $default$;\n"
" $clear_has$;\n"
"}\n");
}
void AccessorEnumFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $default$;\n");
}
void AccessorEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"set$capitalized_name$(input.readInt32());\n");
}
void AccessorEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\n"
" output.writeInt32($number$, $name$_);\n"
"}\n");
}
void AccessorEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeInt32Size($number$, $name$_);\n"
"}\n");
}
string AccessorEnumFieldGenerator::GetBoxedType() const {
return ClassName(params_, descriptor_->enum_type());
}
// ===================================================================
RepeatedEnumFieldGenerator::
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
......@@ -157,7 +241,7 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"public int[] $name$ = com.google.protobuf.nano.WireFormatNano.EMPTY_INT_ARRAY;\n");
"public $type$[] $name$ = $repeated_default$;\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
......@@ -165,7 +249,13 @@ GenerateMembers(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $repeated_default$;\n");
}
void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
if (descriptor_->options().packed()) {
printer->Print(variables_,
......
......@@ -51,7 +51,8 @@ class EnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
......@@ -64,6 +65,28 @@ class EnumFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
};
class AccessorEnumFieldGenerator : public FieldGenerator {
public:
explicit AccessorEnumFieldGenerator(const FieldDescriptor* descriptor,
const Params& params, int has_bit_index);
~AccessorEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator);
};
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
......@@ -71,7 +94,8 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
......
......@@ -53,16 +53,21 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Params
extension_generators_(
new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
int next_has_bit_index = 0;
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset(MakeGenerator(descriptor->field(i), params));
field_generators_[i].reset(
MakeGenerator(descriptor->field(i), params, &next_has_bit_index));
}
for (int i = 0; i < descriptor->extension_count(); i++) {
extension_generators_[i].reset(MakeGenerator(descriptor->extension(i), params));
extension_generators_[i].reset(
MakeGenerator(descriptor->extension(i), params, &next_has_bit_index));
}
total_bits_ = next_has_bit_index;
}
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, const Params &params) {
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index) {
if (field->is_repeated()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
......@@ -72,6 +77,21 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, c
default:
return new RepeatedPrimitiveFieldGenerator(field, params);
}
} else if (params.optional_field_accessors() && field->is_optional()) {
// We need a has-bit for each primitive/enum field because their default
// values could be same as explicitly set values. But we don't need it
// for a message field because they have no defaults and Nano uses 'null'
// for unset messages, which cannot be set explicitly.
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
return new AccessorMessageFieldGenerator(field, params);
case JAVATYPE_ENUM:
return new AccessorEnumFieldGenerator(
field, params, (*next_has_bit_index)++);
default:
return new AccessorPrimitiveFieldGenerator(
field, params, (*next_has_bit_index)++);
}
} else {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
......
......@@ -58,7 +58,8 @@ class FieldGenerator {
virtual ~FieldGenerator();
virtual void GenerateMembers(io::Printer* printer) const = 0;
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
virtual void GenerateClearCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
......@@ -78,13 +79,16 @@ class FieldGeneratorMap {
const FieldGenerator& get(const FieldDescriptor* field) const;
const FieldGenerator& get_extension(int index) const;
int total_bits() const { return total_bits_; }
private:
const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
int total_bits_;
static FieldGenerator* MakeGenerator(const FieldDescriptor* field, const Params &params);
static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
const Params &params, int* next_has_bit_index);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
......
......@@ -138,6 +138,13 @@ bool FileGenerator::Validate(string* error) {
found_conflict = true;
}
}
if (params_.java_enum_style()) {
for (int i = 0; !found_conflict && i < file_->enum_type_count(); i++) {
if (file_->enum_type(i)->name() == classname_) {
found_conflict = true;
}
}
}
if (found_conflict) {
error->assign(file_->name());
error->append(
......@@ -237,6 +244,14 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
file_->message_type(i),
output_directory, file_list, params_);
}
if (params_.java_enum_style()) {
for (int i = 0; i < file_->enum_type_count(); i++) {
GenerateSibling<EnumGenerator>(package_dir, java_package_,
file_->enum_type(i),
output_directory, file_list, params_);
}
}
}
}
......
......@@ -119,12 +119,29 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
} else if (options[i].first == "java_multiple_files") {
params.set_override_java_multiple_files(options[i].second == "true");
} else if (options[i].first == "java_nano_generate_has") {
params.set_generate_has(options[i].second == "true");
params.set_generate_has(options[i].second == "true");
} else if (options[i].first == "enum_style") {
params.set_java_enum_style(options[i].second == "java");
} else if (options[i].first == "optional_field_style") {
params.set_optional_field_accessors(options[i].second == "accessors");
params.set_use_reference_types_for_primitives(options[i].second == "reftypes");
} else {
*error = "Ignore unknown javanano generator option: " + options[i].first;
}
}
// Check illegal parameter combinations
// Note: the enum-like optional_field_style generator param ensures
// that we can never have illegal combinations of field styles
// (e.g. reftypes and accessors can't be on at the same time).
if (params.generate_has()
&& (params.optional_field_accessors()
|| params.use_reference_types_for_primitives())) {
error->assign("java_nano_generate_has=true cannot be used in conjunction"
" with optional_field_style=accessors or optional_field_style=reftypes");
return false;
}
// -----------------------------------------------------------------
FileGenerator file_generator(file, params);
......
......@@ -197,12 +197,23 @@ string FileJavaPackage(const Params& params, const FileDescriptor* file) {
}
bool IsOuterClassNeeded(const Params& params, const FileDescriptor* file) {
// Enums and extensions need the outer class as the scope.
if (file->enum_type_count() != 0 || file->extension_count() != 0) {
// If java_multiple_files is false, the outer class is always needed.
if (!params.java_multiple_files(file->name())) {
return true;
}
// Messages need the outer class only if java_multiple_files is false.
return !params.java_multiple_files(file->name());
// File-scope extensions need the outer class as the scope.
if (file->extension_count() != 0) {
return true;
}
// If container interfaces are not generated, file-scope enums need the
// outer class as the scope.
if (file->enum_type_count() != 0 && !params.java_enum_style()) {
return true;
}
return false;
}
string ToJavaName(const Params& params, const string& name, bool is_class,
......@@ -228,9 +239,14 @@ string ClassName(const Params& params, const FileDescriptor* descriptor) {
}
string ClassName(const Params& params, const EnumDescriptor* descriptor) {
// An enum's class name is the enclosing message's class name or the outer
// class name.
const Descriptor* parent = descriptor->containing_type();
// When using Java enum style, an enum's class name contains the enum name.
// Use the standard ToJavaName translation.
if (params.java_enum_style()) {
return ToJavaName(params, descriptor->name(), true, parent,
descriptor->file());
}
// Otherwise the enum members are accessed from the enclosing class.
if (parent != NULL) {
return ClassName(params, parent);
} else {
......@@ -341,6 +357,10 @@ string DefaultValue(const Params& params, const FieldDescriptor* field) {
return EmptyArrayName(params, field);
}
if (params.use_reference_types_for_primitives()) {
return "null";
}
// Switch on cpp_type since we need to know which default_value_* method
// of FieldDescriptor to call.
switch (field->cpp_type()) {
......@@ -407,6 +427,90 @@ string DefaultValue(const Params& params, const FieldDescriptor* field) {
return "";
}
static const char* kBitMasks[] = {
"0x00000001",
"0x00000002",
"0x00000004",
"0x00000008",
"0x00000010",
"0x00000020",
"0x00000040",
"0x00000080",
"0x00000100",
"0x00000200",
"0x00000400",
"0x00000800",
"0x00001000",
"0x00002000",
"0x00004000",
"0x00008000",
"0x00010000",
"0x00020000",
"0x00040000",
"0x00080000",
"0x00100000",
"0x00200000",
"0x00400000",
"0x00800000",
"0x01000000",
"0x02000000",
"0x04000000",
"0x08000000",
"0x10000000",
"0x20000000",
"0x40000000",
"0x80000000",
};
string GetBitFieldName(int index) {
string var_name = "bitField";
var_name += SimpleItoa(index);
var_name += "_";
return var_name;
}
string GetBitFieldNameForBit(int bit_index) {
return GetBitFieldName(bit_index / 32);
}
string GenerateGetBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = "((" + var_name + " & " + mask + ") == " + mask + ")";
return result;
}
string GenerateSetBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = var_name + " |= " + mask;
return result;
}
string GenerateClearBit(int bit_index) {
string var_name = GetBitFieldNameForBit(bit_index);
int bit_in_var_index = bit_index % 32;
string mask = kBitMasks[bit_in_var_index];
string result = var_name + " = (" + var_name + " & ~" + mask + ")";
return result;
}
void SetBitOperationVariables(const string name,
int bitIndex, map<string, string>* variables) {
(*variables)["get_" + name] = GenerateGetBit(bitIndex);
(*variables)["set_" + name] = GenerateSetBit(bitIndex);
(*variables)["clear_" + name] = GenerateClearBit(bitIndex);
}
} // namespace javanano
} // namespace compiler
} // namespace protobuf
......
......@@ -138,6 +138,36 @@ string EmptyArrayName(const Params& params, const FieldDescriptor* field);
string DefaultValue(const Params& params, const FieldDescriptor* field);
// Methods for shared bitfields.
// Gets the name of the shared bitfield for the given index.
string GetBitFieldName(int index);
// Gets the name of the shared bitfield for the given bit index.
// Effectively, GetBitFieldName(bit_index / 32)
string GetBitFieldNameForBit(int bit_index);
// Generates the java code for the expression that returns the boolean value
// of the bit of the shared bitfields for the given bit index.
// Example: "((bitField1_ & 0x04) == 0x04)"
string GenerateGetBit(int bit_index);
// Generates the java code for the expression that sets the bit of the shared
// bitfields for the given bit index.
// Example: "bitField1_ = (bitField1_ | 0x04)"
string GenerateSetBit(int bit_index);
// Generates the java code for the expression that clears the bit of the shared
// bitfields for the given bit index.
// Example: "bitField1_ = (bitField1_ & ~0x04)"
string GenerateClearBit(int bit_index);
// Sets the 'get_*', 'set_*' and 'clear_*' variables, where * is the given bit
// field name, to the appropriate Java expressions for the given bit index.
void SetBitOperationVariables(const string name,
int bitIndex, map<string, string>* variables);
} // namespace javanano
} // namespace compiler
} // namespace protobuf
......
......@@ -137,9 +137,9 @@ void MessageGenerator::Generate(io::Printer* printer) {
// warnings here in the class declaration.
printer->Print(
"@SuppressWarnings(\"hiding\")\n"
"public $modifiers$ final class $classname$ extends\n"
"public $modifiers$final class $classname$ extends\n"
" com.google.protobuf.nano.MessageNano {\n",
"modifiers", is_own_file ? "" : "static",
"modifiers", is_own_file ? "" : "static ",
"classname", descriptor_->name());
printer->Indent();
printer->Print(
......@@ -167,6 +167,13 @@ void MessageGenerator::Generate(io::Printer* printer) {
MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
}
// Integers for bit fields
int totalInts = (field_generators_.total_bits() + 31) / 32;
for (int i = 0; i < totalInts; i++) {
printer->Print("private int $bit_field_name$;\n",
"bit_field_name", GetBitFieldName(i));
}
// Fields
for (int i = 0; i < descriptor_->field_count(); i++) {
PrintFieldComment(printer, descriptor_->field(i));
......@@ -327,7 +334,7 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
"tag", SimpleItoa(tag));
printer->Indent();
field_generators_.get(field).GenerateParsingCode(printer);
field_generators_.get(field).GenerateMergingCode(printer);
printer->Outdent();
printer->Print(
......@@ -376,33 +383,17 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
// Clear bit fields.
int totalInts = (field_generators_.total_bits() + 31) / 32;
for (int i = 0; i < totalInts; i++) {
printer->Print("$bit_field_name$ = 0;\n",
"bit_field_name", GetBitFieldName(i));
}
// Call clear for all of the fields.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->type() == FieldDescriptor::TYPE_BYTES &&
!field->default_value_string().empty()) {
// Need to clone the default value because it is of a mutable
// type.
printer->Print(
"$name$ = $default$.clone();\n",
"name", RenameJavaKeywords(UnderscoresToCamelCase(field)),
"default", DefaultValue(params_, field));
} else {
printer->Print(
"$name$ = $default$;\n",
"name", RenameJavaKeywords(UnderscoresToCamelCase(field)),
"default", DefaultValue(params_, field));
}
if (params_.generate_has() &&
field->label() != FieldDescriptor::LABEL_REPEATED &&
field->type() != FieldDescriptor::TYPE_GROUP &&
field->type() != FieldDescriptor::TYPE_MESSAGE) {
printer->Print(
"has$capitalized_name$ = false;\n",
"capitalized_name", UnderscoresToCapitalizedCamelCase(field));
}
field_generators_.get(field).GenerateClearCode(printer);
}
// Clear unknown fields.
......
......@@ -88,9 +88,17 @@ GenerateMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"this.$name$ = new $type$();\n");
"$name$ = null;\n");
}
void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ == null) {\n"
" this.$name$ = new $type$();\n"
"}");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
......@@ -124,6 +132,81 @@ string MessageFieldGenerator::GetBoxedType() const {
// ===================================================================
AccessorMessageFieldGenerator::
AccessorMessageFieldGenerator(
const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetMessageVariables(params, descriptor, &variables_);
}
AccessorMessageFieldGenerator::~AccessorMessageFieldGenerator() {}
void AccessorMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $type$ $name$_ = null;\n"
"public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
"public void set$capitalized_name$($type$ value) {\n"
" if (value == null) {\n"
" throw new java.lang.NullPointerException();\n"
" }\n"
" $name$_ = value;\n"
"}\n"
"public boolean has$capitalized_name$() {\n"
" return $name$_ != null;\n"
"}\n"
"public void clear$capitalized_name$() {\n"
" $name$_ = null;\n"
"}\n");
}
void AccessorMessageFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = null;\n");
}
void AccessorMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!has$capitalized_name$()) {\n"
" set$capitalized_name$(new $type$());\n"
"}");
if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($name$_, $number$);\n");
} else {
printer->Print(variables_,
"input.readMessage($name$_);\n");
}
}
void AccessorMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\n"
" output.write$group_or_message$($number$, $name$_);\n"
"}\n");
}
void AccessorMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$group_or_message$Size($number$, $name$_);\n"
"}\n");
}
string AccessorMessageFieldGenerator::GetBoxedType() const {
return ClassName(params_, descriptor_->message_type());
}
// ===================================================================
RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
......@@ -139,7 +222,13 @@ GenerateMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $type$.EMPTY_ARRAY;\n");
}
void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
printer->Print(variables_,
"int arrayLength = com.google.protobuf.nano.WireFormatNano.getRepeatedFieldArrayLength(input, $tag$);\n"
......
......@@ -51,7 +51,8 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
......@@ -64,6 +65,28 @@ class MessageFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
};
class AccessorMessageFieldGenerator : public FieldGenerator {
public:
explicit AccessorMessageFieldGenerator(
const FieldDescriptor* descriptor, const Params& params);
~AccessorMessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorMessageFieldGenerator);
};
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
......@@ -72,7 +95,8 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
......
......@@ -58,6 +58,9 @@ class Params {
NameMap java_outer_classnames_;
NameSet java_multiple_files_;
bool generate_has_;
bool java_enum_style_;
bool optional_field_accessors_;
bool use_reference_types_for_primitives_;
public:
Params(const string & base_name) :
......@@ -65,7 +68,10 @@ class Params {
base_name_(base_name),
override_java_multiple_files_(JAVANANO_MUL_UNSET),
store_unknown_fields_(false),
generate_has_(false) {
generate_has_(false),
java_enum_style_(false),
optional_field_accessors_(false),
use_reference_types_for_primitives_(false) {
}
const string& base_name() const {
......@@ -160,6 +166,26 @@ class Params {
return generate_has_;
}
void set_java_enum_style(bool value) {
java_enum_style_ = value;
}
bool java_enum_style() const {
return java_enum_style_;
}
void set_optional_field_accessors(bool value) {
optional_field_accessors_ = value;
}
bool optional_field_accessors() const {
return optional_field_accessors_;
}
void set_use_reference_types_for_primitives(bool value) {
use_reference_types_for_primitives_ = value;
}
bool use_reference_types_for_primitives() const {
return use_reference_types_for_primitives_;
}
};
} // namespace javanano
......
......@@ -245,7 +245,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param
(*variables)["capitalized_name"] =
RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor));
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
if (params.use_reference_types_for_primitives()
&& !descriptor->is_repeated()) {
(*variables)["type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
} else {
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
}
(*variables)["default"] = DefaultValue(params, descriptor);
(*variables)["default_constant"] = FieldDefaultConstantName(descriptor);
// For C++-string types (string and bytes), we might need to have
......@@ -254,12 +259,14 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param
// once into a "private static final" field and re-use that from
// then on.
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
!descriptor->default_value_string().empty()) {
!descriptor->default_value_string().empty() &&
!params.use_reference_types_for_primitives()) {
string default_value;
if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
default_value = strings::Substitute(
"com.google.protobuf.nano.InternalNano.bytesDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string()));
(*variables)["default_copy_if_needed"] = (*variables)["default"] + ".clone()";
} else {
if (AllAscii(descriptor->default_value_string())) {
// All chars are ASCII. In this case CEscape() works fine.
......@@ -269,22 +276,17 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params param
"com.google.protobuf.nano.InternalNano.stringDefaultValue(\"$0\")",
CEscape(descriptor->default_value_string()));
}
(*variables)["default_copy_if_needed"] = (*variables)["default"];
}
(*variables)["default_constant_value"] = default_value;
} else {
(*variables)["default_copy_if_needed"] = (*variables)["default"];
}
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
if (IsReferenceType(GetJavaType(descriptor))) {
(*variables)["null_check"] =
" if (value == null) {\n"
" throw new NullPointerException();\n"
" }\n";
} else {
(*variables)["null_check"] = "";
}
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
......@@ -310,18 +312,11 @@ GenerateMembers(io::Printer* printer) const {
// Those primitive types that need a saved default.
printer->Print(variables_,
"private static final $type$ $default_constant$ = $default_constant_value$;\n");
if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
printer->Print(variables_,
"public $type$ $name$ = $default$.clone();\n");
} else {
printer->Print(variables_,
"public $type$ $name$ = $default$;\n");
}
} else {
printer->Print(variables_,
"public $type$ $name$ = $default$;\n");
}
printer->Print(variables_,
"public $type$ $name$ = $default_copy_if_needed$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"public boolean has$capitalized_name$ = false;\n");
......@@ -329,7 +324,18 @@ GenerateMembers(io::Printer* printer) const {
}
void PrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $default_copy_if_needed$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
"has$capitalized_name$ = false;\n");
}
}
void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"this.$name$ = input.read$capitalized_type$();\n");
......@@ -341,6 +347,13 @@ GenerateParsingCode(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateSerializationConditional(io::Printer* printer) const {
if (params_.use_reference_types_for_primitives()) {
// For reference type mode, serialize based on equality
// to null.
printer->Print(variables_,
"if (this.$name$ != null) {\n");
return;
}
if (params_.generate_has()) {
printer->Print(variables_,
"if (has$capitalized_name$ || ");
......@@ -397,6 +410,80 @@ string PrimitiveFieldGenerator::GetBoxedType() const {
// ===================================================================
AccessorPrimitiveFieldGenerator::
AccessorPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
const Params& params, int has_bit_index)
: FieldGenerator(params), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, params, &variables_);
SetBitOperationVariables("has", has_bit_index, &variables_);
}
AccessorPrimitiveFieldGenerator::~AccessorPrimitiveFieldGenerator() {}
void AccessorPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const {
if (variables_.find("default_constant_value") != variables_.end()) {
printer->Print(variables_,
"private static final $type$ $default_constant$ = $default_constant_value$;\n");
}
printer->Print(variables_,
"private $type$ $name$_ = $default_copy_if_needed$;\n"
"public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
"public void set$capitalized_name$($type$ value) {\n");
if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
" if (value == null) throw new java.lang.NullPointerException();\n");
}
printer->Print(variables_,
" $name$_ = value;\n"
" $set_has$;\n"
"}\n"
"public boolean has$capitalized_name$() {\n"
" return $get_has$;\n"
"}\n"
"public void clear$capitalized_name$() {\n"
" $name$_ = $default_copy_if_needed$;\n"
" $clear_has$;\n"
"}\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $default_copy_if_needed$;\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"set$capitalized_name$(input.read$capitalized_type$());\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\n"
" output.write$capitalized_type$($number$, $name$_);\n"
"}\n");
}
void AccessorPrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$Size($number$, $name$_);\n"
"}\n");
}
string AccessorPrimitiveFieldGenerator::GetBoxedType() const {
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
}
// ===================================================================
RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
......@@ -412,7 +499,13 @@ GenerateMembers(io::Printer* printer) const {
}
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
GenerateClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$ = $default$;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
if (descriptor_->options().packed()) {
printer->Print(variables_,
......
......@@ -51,7 +51,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
......@@ -66,6 +67,28 @@ class PrimitiveFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
};
class AccessorPrimitiveFieldGenerator : public FieldGenerator {
public:
explicit AccessorPrimitiveFieldGenerator( const FieldDescriptor* descriptor,
const Params &params, int has_bit_index);
~AccessorPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
};
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
......@@ -73,7 +96,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateClearCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
......
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoAccessorsOuterClass";
message TestNanoAccessors {
message NestedMessage {
optional int32 bb = 1;
}
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
// Singular
optional int32 optional_int32 = 1;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional NestedMessage optional_nested_message = 18;
optional NestedEnum optional_nested_enum = 21;
// Repeated
repeated int32 repeated_int32 = 31;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated NestedMessage repeated_nested_message = 48;
repeated NestedEnum repeated_nested_enum = 51;
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional float default_float_nan = 99 [default = nan];
optional NestedEnum default_nested_enum = 81 [default = BAR];
// Required
required int32 id = 86;
// Add enough optional fields to make 2 bit fields in total
optional int32 filler100 = 100;
optional int32 filler101 = 101;
optional int32 filler102 = 102;
optional int32 filler103 = 103;
optional int32 filler104 = 104;
optional int32 filler105 = 105;
optional int32 filler106 = 106;
optional int32 filler107 = 107;
optional int32 filler108 = 108;
optional int32 filler109 = 109;
optional int32 filler110 = 110;
optional int32 filler111 = 111;
optional int32 filler112 = 112;
optional int32 filler113 = 113;
optional int32 filler114 = 114;
optional int32 filler115 = 115;
optional int32 filler116 = 116;
optional int32 filler117 = 117;
optional int32 filler118 = 118;
optional int32 filler119 = 119;
optional int32 filler120 = 120;
optional int32 filler121 = 121;
optional int32 filler122 = 122;
optional int32 filler123 = 123;
optional int32 filler124 = 124;
optional int32 filler125 = 125;
optional int32 filler126 = 126;
optional int32 filler127 = 127;
optional int32 filler128 = 128;
optional int32 filler129 = 129;
optional int32 filler130 = 130;
optional int32 before_bit_field_check = 139;
optional int32 bit_field_check = 140;
optional int32 after_bit_field_check = 141;
}
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_multiple_files = true;
enum FileScopeEnumMultiple {
THREE = 3;
}
message EnumClassNanoMultiple {
enum MessageScopeEnumMultiple {
FOUR = 4;
}
optional FileScopeEnumMultiple three = 3 [ default = THREE ];
optional MessageScopeEnumMultiple four = 4 [ default = FOUR ];
}
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// 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.
// Author: maxtroy@google.com (Max Cai)
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "EnumClassNanos";
enum FileScopeEnum {
ONE = 1;
}
message EnumClassNano {
enum MessageScopeEnum {
TWO = 2;
}
optional FileScopeEnum one = 1 [ default = ONE ];
optional MessageScopeEnum two = 2 [ default = TWO ];
}
......@@ -42,3 +42,9 @@ message ContainerMessage {
optional bool another_thing = 100;
}
}
message MessageWithGroup {
optional group Group = 1 {
optional int32 a = 2;
}
}
package protobuf_unittest;
option java_package = "com.google.protobuf.nano";
option java_outer_classname = "NanoReferenceTypes";
message TestAllTypesNano {
enum NestedEnum {
FOO = 1;
BAR = 2;
BAZ = 3;
}
message NestedMessage {
optional int32 foo = 1;
}
// Singular
optional int32 optional_int32 = 1;
optional int64 optional_int64 = 2;
optional uint32 optional_uint32 = 3;
optional uint64 optional_uint64 = 4;
optional sint32 optional_sint32 = 5;
optional sint64 optional_sint64 = 6;
optional fixed32 optional_fixed32 = 7;
optional fixed64 optional_fixed64 = 8;
optional sfixed32 optional_sfixed32 = 9;
optional sfixed64 optional_sfixed64 = 10;
optional float optional_float = 11;
optional double optional_double = 12;
optional bool optional_bool = 13;
optional string optional_string = 14;
optional bytes optional_bytes = 15;
optional group OptionalGroup = 16 {
optional int32 a = 17;
}
optional NestedMessage optional_nested_message = 18;
optional NestedEnum optional_nested_enum = 21;
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
repeated uint32 repeated_uint32 = 33;
repeated uint64 repeated_uint64 = 34;
repeated sint32 repeated_sint32 = 35;
repeated sint64 repeated_sint64 = 36;
repeated fixed32 repeated_fixed32 = 37;
repeated fixed64 repeated_fixed64 = 38;
repeated sfixed32 repeated_sfixed32 = 39;
repeated sfixed64 repeated_sfixed64 = 40;
repeated float repeated_float = 41;
repeated double repeated_double = 42;
repeated bool repeated_bool = 43;
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
repeated group RepeatedGroup = 46 {
optional int32 a = 47;
}
repeated NestedMessage repeated_nested_message = 48;
repeated NestedEnum repeated_nested_enum = 51;
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
// Repeated packed
repeated int32 repeated_packed_int32 = 87 [packed=true];
repeated sfixed64 repeated_packed_sfixed64 = 88 [packed=true];
repeated NestedEnum repeated_packed_nested_enum = 89 [packed=true];
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
optional uint32 default_uint32 = 63 [default = 43 ];
optional uint64 default_uint64 = 64 [default = 44 ];
optional sint32 default_sint32 = 65 [default = -45 ];
optional sint64 default_sint64 = 66 [default = 46 ];
optional fixed32 default_fixed32 = 67 [default = 47 ];
optional fixed64 default_fixed64 = 68 [default = 48 ];
optional sfixed32 default_sfixed32 = 69 [default = 49 ];
optional sfixed64 default_sfixed64 = 70 [default = -50 ];
optional float default_float = 71 [default = 51.5 ];
optional double default_double = 72 [default = 52e3 ];
optional bool default_bool = 73 [default = true ];
optional string default_string = 74 [default = "hello"];
optional bytes default_bytes = 75 [default = "world"];
optional float default_float_inf = 97 [default = inf];
optional float default_float_neg_inf = 98 [default = -inf];
optional float default_float_nan = 99 [default = nan];
optional double default_double_inf = 100 [default = inf];
optional double default_double_neg_inf = 101 [default = -inf];
optional double default_double_nan = 102 [default = nan];
}
message ForeignMessageNano {
optional int32 c = 1;
}
enum ForeignEnumNano {
FOREIGN_NANO_FOO = 4;
FOREIGN_NANO_BAR = 5;
FOREIGN_NANO_BAZ = 6;
}
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