Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
30b1454d
Commit
30b1454d
authored
Jul 15, 2014
by
Max Cai
Committed by
Gerrit Code Review
Jul 14, 2014
Browse files
Options
Browse Files
Download
Plain Diff
Merge "Keep pointers to extension values."
parents
70ef74aa
79f19eb9
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
917 additions
and
253 deletions
+917
-253
README.txt
java/README.txt
+4
-3
ExtendableMessageNano.java
.../java/com/google/protobuf/nano/ExtendableMessageNano.java
+52
-19
Extension.java
java/src/main/java/com/google/protobuf/nano/Extension.java
+240
-206
FieldArray.java
java/src/main/java/com/google/protobuf/nano/FieldArray.java
+273
-0
FieldData.java
java/src/main/java/com/google/protobuf/nano/FieldData.java
+173
-0
UnknownFieldData.java
.../main/java/com/google/protobuf/nano/UnknownFieldData.java
+38
-25
NanoTest.java
java/src/test/java/com/google/protobuf/NanoTest.java
+137
-0
No files found.
java/README.txt
View file @
30b1454d
...
@@ -442,9 +442,10 @@ used simultaneously from multiple threads in a read-only manner.
...
@@ -442,9 +442,10 @@ used simultaneously from multiple threads in a read-only manner.
In other words, an appropriate synchronization mechanism (such as
In other words, an appropriate synchronization mechanism (such as
a ReadWriteLock) must be used to ensure that a message, its
a ReadWriteLock) must be used to ensure that a message, its
ancestors, and descendants are not accessed by any other threads
ancestors, and descendants are not accessed by any other threads
while the message is being modified. Field reads, getter methods,
while the message is being modified. Field reads, getter methods
toByteArray(...), writeTo(...), getCachedSize(), and
(but not getExtension(...)), toByteArray(...), writeTo(...),
getSerializedSize() are all considered read-only operations.
getCachedSize(), and getSerializedSize() are all considered read-only
operations.
IMPORTANT: If you have fields with defaults and opt out of accessors
IMPORTANT: If you have fields with defaults and opt out of accessors
...
...
java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
View file @
30b1454d
...
@@ -31,8 +31,6 @@
...
@@ -31,8 +31,6 @@
package
com
.
google
.
protobuf
.
nano
;
package
com
.
google
.
protobuf
.
nano
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
/**
* Base class of those Protocol Buffer messages that need to store unknown fields,
* Base class of those Protocol Buffer messages that need to store unknown fields,
...
@@ -44,27 +42,28 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
...
@@ -44,27 +42,28 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
* A container for fields unknown to the message, including extensions. Extension fields can
* A container for fields unknown to the message, including extensions. Extension fields can
* can be accessed through the {@link #getExtension} and {@link #setExtension} methods.
* can be accessed through the {@link #getExtension} and {@link #setExtension} methods.
*/
*/
protected
List
<
UnknownFieldData
>
unknownFieldData
;
protected
FieldArray
unknownFieldData
;
@Override
@Override
protected
int
computeSerializedSize
()
{
protected
int
computeSerializedSize
()
{
int
size
=
0
;
int
size
=
0
;
i
nt
unknownFieldCount
=
unknownFieldData
==
null
?
0
:
unknownFieldData
.
size
();
i
f
(
unknownFieldData
!=
null
)
{
for
(
int
i
=
0
;
i
<
unknownFieldCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
unknownFieldData
.
size
()
;
i
++)
{
UnknownFieldData
unknownField
=
unknownFieldData
.
ge
t
(
i
);
FieldData
field
=
unknownFieldData
.
dataA
t
(
i
);
size
+=
CodedOutputByteBufferNano
.
computeRawVarint32Size
(
unknownField
.
tag
);
size
+=
field
.
computeSerializedSize
(
);
size
+=
unknownField
.
bytes
.
length
;
}
}
}
return
size
;
return
size
;
}
}
@Override
@Override
public
void
writeTo
(
CodedOutputByteBufferNano
output
)
throws
IOException
{
public
void
writeTo
(
CodedOutputByteBufferNano
output
)
throws
IOException
{
int
unknownFieldCount
=
unknownFieldData
==
null
?
0
:
unknownFieldData
.
size
();
if
(
unknownFieldData
==
null
)
{
for
(
int
i
=
0
;
i
<
unknownFieldCount
;
i
++)
{
return
;
UnknownFieldData
unknownField
=
unknownFieldData
.
get
(
i
);
}
output
.
writeRawVarint32
(
unknownField
.
tag
);
for
(
int
i
=
0
;
i
<
unknownFieldData
.
size
();
i
++)
{
output
.
writeRawBytes
(
unknownField
.
bytes
);
FieldData
field
=
unknownFieldData
.
dataAt
(
i
);
field
.
writeTo
(
output
);
}
}
}
}
...
@@ -72,14 +71,38 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
...
@@ -72,14 +71,38 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
* Gets the value stored in the specified extension of this message.
* Gets the value stored in the specified extension of this message.
*/
*/
public
final
<
T
>
T
getExtension
(
Extension
<
M
,
T
>
extension
)
{
public
final
<
T
>
T
getExtension
(
Extension
<
M
,
T
>
extension
)
{
return
extension
.
getValueFrom
(
unknownFieldData
);
if
(
unknownFieldData
==
null
)
{
return
null
;
}
FieldData
field
=
unknownFieldData
.
get
(
WireFormatNano
.
getTagFieldNumber
(
extension
.
tag
));
return
field
==
null
?
null
:
field
.
getValue
(
extension
);
}
}
/**
/**
* Sets the value of the specified extension of this message.
* Sets the value of the specified extension of this message.
*/
*/
public
final
<
T
>
M
setExtension
(
Extension
<
M
,
T
>
extension
,
T
value
)
{
public
final
<
T
>
M
setExtension
(
Extension
<
M
,
T
>
extension
,
T
value
)
{
unknownFieldData
=
extension
.
setValueTo
(
value
,
unknownFieldData
);
int
fieldNumber
=
WireFormatNano
.
getTagFieldNumber
(
extension
.
tag
);
if
(
value
==
null
)
{
if
(
unknownFieldData
!=
null
)
{
unknownFieldData
.
remove
(
fieldNumber
);
if
(
unknownFieldData
.
isEmpty
())
{
unknownFieldData
=
null
;
}
}
}
else
{
FieldData
field
=
null
;
if
(
unknownFieldData
==
null
)
{
unknownFieldData
=
new
FieldArray
();
}
else
{
field
=
unknownFieldData
.
get
(
fieldNumber
);
}
if
(
field
==
null
)
{
unknownFieldData
.
put
(
fieldNumber
,
new
FieldData
(
extension
,
value
));
}
else
{
field
.
setValue
(
extension
,
value
);
}
}
@SuppressWarnings
(
"unchecked"
)
// Generated code should guarantee type safety
@SuppressWarnings
(
"unchecked"
)
// Generated code should guarantee type safety
M
typedThis
=
(
M
)
this
;
M
typedThis
=
(
M
)
this
;
...
@@ -106,12 +129,22 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
...
@@ -106,12 +129,22 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
if
(!
input
.
skipField
(
tag
))
{
if
(!
input
.
skipField
(
tag
))
{
return
false
;
// This wasn't an unknown field, it's an end-group tag.
return
false
;
// This wasn't an unknown field, it's an end-group tag.
}
}
if
(
unknownFieldData
==
null
)
{
int
fieldNumber
=
WireFormatNano
.
getTagFieldNumber
(
tag
);
unknownFieldData
=
new
ArrayList
<
UnknownFieldData
>();
}
int
endPos
=
input
.
getPosition
();
int
endPos
=
input
.
getPosition
();
byte
[]
bytes
=
input
.
getData
(
startPos
,
endPos
-
startPos
);
byte
[]
bytes
=
input
.
getData
(
startPos
,
endPos
-
startPos
);
unknownFieldData
.
add
(
new
UnknownFieldData
(
tag
,
bytes
));
UnknownFieldData
unknownField
=
new
UnknownFieldData
(
tag
,
bytes
);
FieldData
field
=
null
;
if
(
unknownFieldData
==
null
)
{
unknownFieldData
=
new
FieldArray
();
}
else
{
field
=
unknownFieldData
.
get
(
fieldNumber
);
}
if
(
field
==
null
)
{
field
=
new
FieldData
();
unknownFieldData
.
put
(
fieldNumber
,
field
);
}
field
.
addUnknownField
(
unknownField
);
return
true
;
return
true
;
}
}
}
}
java/src/main/java/com/google/protobuf/nano/Extension.java
View file @
30b1454d
...
@@ -152,56 +152,50 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -152,56 +152,50 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
this
.
repeated
=
repeated
;
this
.
repeated
=
repeated
;
}
}
protected
boolean
isMatch
(
int
unknownDataTag
)
{
// This implementation is for message/group extensions.
return
unknownDataTag
==
tag
;
}
/**
/**
* Returns the value of this extension stored in the given list of unknown fields, or
* Returns the value of this extension stored in the given list of unknown fields, or
* {@code null} if no unknown fields matches this extension.
* {@code null} if no unknown fields matches this extension.
*
* @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag
* that matches this Extension's tag.
*
*/
*/
final
T
getValueFrom
(
List
<
UnknownFieldData
>
unknownFields
)
{
final
T
getValueFrom
(
List
<
UnknownFieldData
>
unknownFields
)
{
if
(
unknownFields
==
null
)
{
if
(
unknownFields
==
null
)
{
return
null
;
return
null
;
}
}
return
repeated
?
getRepeatedValueFrom
(
unknownFields
)
:
getSingularValueFrom
(
unknownFields
);
}
if
(
repeated
)
{
private
T
getRepeatedValueFrom
(
List
<
UnknownFieldData
>
unknownFields
)
{
// For repeated extensions, read all matching unknown fields in their original order.
// For repeated extensions, read all matching unknown fields in their original order.
List
<
Object
>
resultList
=
new
ArrayList
<
Object
>();
List
<
Object
>
resultList
=
new
ArrayList
<
Object
>();
for
(
int
i
=
0
;
i
<
unknownFields
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
unknownFields
.
size
();
i
++)
{
UnknownFieldData
data
=
unknownFields
.
get
(
i
);
UnknownFieldData
data
=
unknownFields
.
get
(
i
);
if
(
isMatch
(
data
.
tag
)
&&
data
.
bytes
.
length
!=
0
)
{
if
(
data
.
bytes
.
length
!=
0
)
{
readDataInto
(
data
,
resultList
);
readDataInto
(
data
,
resultList
);
}
}
int
resultSize
=
resultList
.
size
();
if
(
resultSize
==
0
)
{
return
null
;
}
}
}
int
resultSize
=
resultList
.
size
();
if
(
resultSize
==
0
)
{
return
null
;
}
else
{
T
result
=
clazz
.
cast
(
Array
.
newInstance
(
clazz
.
getComponentType
(),
resultSize
));
T
result
=
clazz
.
cast
(
Array
.
newInstance
(
clazz
.
getComponentType
(),
resultSize
));
for
(
int
i
=
0
;
i
<
resultSize
;
i
++)
{
for
(
int
i
=
0
;
i
<
resultSize
;
i
++)
{
Array
.
set
(
result
,
i
,
resultList
.
get
(
i
));
Array
.
set
(
result
,
i
,
resultList
.
get
(
i
));
}
}
return
result
;
return
result
;
}
else
{
}
// For singular extensions, get the last piece of data stored under this extension.
}
UnknownFieldData
lastData
=
null
;
for
(
int
i
=
unknownFields
.
size
()
-
1
;
lastData
==
null
&&
i
>=
0
;
i
--)
{
UnknownFieldData
data
=
unknownFields
.
get
(
i
);
if
(
isMatch
(
data
.
tag
)
&&
data
.
bytes
.
length
!=
0
)
{
lastData
=
data
;
}
}
if
(
lastData
==
null
)
{
return
null
;
}
return
clazz
.
cast
(
readData
(
CodedInputByteBufferNano
.
newInstance
(
lastData
.
bytes
)));
private
T
getSingularValueFrom
(
List
<
UnknownFieldData
>
unknownFields
)
{
// For singular extensions, get the last piece of data stored under this extension.
if
(
unknownFields
.
isEmpty
())
{
return
null
;
}
}
UnknownFieldData
lastData
=
unknownFields
.
get
(
unknownFields
.
size
()
-
1
);
return
clazz
.
cast
(
readData
(
CodedInputByteBufferNano
.
newInstance
(
lastData
.
bytes
)));
}
}
protected
Object
readData
(
CodedInputByteBufferNano
input
)
{
protected
Object
readData
(
CodedInputByteBufferNano
input
)
{
...
@@ -236,61 +230,29 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -236,61 +230,29 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
resultList
.
add
(
readData
(
CodedInputByteBufferNano
.
newInstance
(
data
.
bytes
)));
resultList
.
add
(
readData
(
CodedInputByteBufferNano
.
newInstance
(
data
.
bytes
)));
}
}
/**
void
writeTo
(
Object
value
,
CodedOutputByteBufferNano
output
)
throws
IOException
{
* Sets the value of this extension to the given list of unknown fields. This removes any
if
(
repeated
)
{
* previously stored data matching this extension.
writeRepeatedData
(
value
,
output
);
*
}
else
{
* @param value The value of this extension, or {@code null} to clear this extension from the
writeSingularData
(
value
,
output
);
* unknown fields.
* @return The same {@code unknownFields} list, or a new list storing the extension value if
* the argument was null.
*/
final
List
<
UnknownFieldData
>
setValueTo
(
T
value
,
List
<
UnknownFieldData
>
unknownFields
)
{
if
(
unknownFields
!=
null
)
{
// Delete all data matching this extension
for
(
int
i
=
unknownFields
.
size
()
-
1
;
i
>=
0
;
i
--)
{
if
(
isMatch
(
unknownFields
.
get
(
i
).
tag
))
{
unknownFields
.
remove
(
i
);
}
}
}
if
(
value
!=
null
)
{
if
(
unknownFields
==
null
)
{
unknownFields
=
new
ArrayList
<
UnknownFieldData
>();
}
if
(
repeated
)
{
writeDataInto
(
value
,
unknownFields
);
}
else
{
unknownFields
.
add
(
writeData
(
value
));
}
}
}
// After deletion or no-op addition (due to 'value' being an array of empty or
// null-only elements), unknownFields may be empty. Discard the ArrayList if so.
return
(
unknownFields
==
null
||
unknownFields
.
isEmpty
())
?
null
:
unknownFields
;
}
}
protected
UnknownFieldData
writeData
(
Object
value
)
{
protected
void
writeSingularData
(
Object
value
,
CodedOutputByteBufferNano
out
)
{
// This implementation is for message/group extensions.
// This implementation is for message/group extensions.
byte
[]
data
;
try
{
try
{
out
.
writeRawVarint32
(
tag
);
switch
(
type
)
{
switch
(
type
)
{
case
TYPE_GROUP:
case
TYPE_GROUP:
MessageNano
groupValue
=
(
MessageNano
)
value
;
MessageNano
groupValue
=
(
MessageNano
)
value
;
int
fieldNumber
=
WireFormatNano
.
getTagFieldNumber
(
tag
);
int
fieldNumber
=
WireFormatNano
.
getTagFieldNumber
(
tag
);
data
=
new
byte
[
CodedOutputByteBufferNano
.
computeGroupSizeNoTag
(
groupValue
)
+
CodedOutputByteBufferNano
.
computeTagSize
(
fieldNumber
)];
CodedOutputByteBufferNano
out
=
CodedOutputByteBufferNano
.
newInstance
(
data
);
out
.
writeGroupNoTag
(
groupValue
);
out
.
writeGroupNoTag
(
groupValue
);
// The endgroup tag must be included in the data payload.
// The endgroup tag must be included in the data payload.
out
.
writeTag
(
fieldNumber
,
WireFormatNano
.
WIRETYPE_END_GROUP
);
out
.
writeTag
(
fieldNumber
,
WireFormatNano
.
WIRETYPE_END_GROUP
);
break
;
break
;
case
TYPE_MESSAGE:
case
TYPE_MESSAGE:
MessageNano
messageValue
=
(
MessageNano
)
value
;
MessageNano
messageValue
=
(
MessageNano
)
value
;
data
=
new
byte
[
out
.
writeMessageNoTag
(
messageValue
);
CodedOutputByteBufferNano
.
computeMessageSizeNoTag
(
messageValue
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeMessageNoTag
(
messageValue
);
break
;
break
;
default
:
default
:
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
...
@@ -299,18 +261,53 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -299,18 +261,53 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
// Should not happen
// Should not happen
throw
new
IllegalStateException
(
e
);
throw
new
IllegalStateException
(
e
);
}
}
return
new
UnknownFieldData
(
tag
,
data
);
}
}
protected
void
writeDataInto
(
T
array
,
List
<
UnknownFieldData
>
unknownFields
)
{
protected
void
writeRepeatedData
(
Object
array
,
CodedOutputByteBufferNano
output
)
{
// This implementation is for non-packed extensions.
int
arrayLength
=
Array
.
getLength
(
array
);
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
Object
element
=
Array
.
get
(
array
,
i
);
if
(
element
!=
null
)
{
writeSingularData
(
element
,
output
);
}
}
}
int
computeSerializedSize
(
Object
value
)
{
if
(
repeated
)
{
return
computeRepeatedSerializedSize
(
value
);
}
else
{
return
computeSingularSerializedSize
(
value
);
}
}
protected
int
computeRepeatedSerializedSize
(
Object
array
)
{
// This implementation is for non-packed extensions.
// This implementation is for non-packed extensions.
int
size
=
0
;
int
arrayLength
=
Array
.
getLength
(
array
);
int
arrayLength
=
Array
.
getLength
(
array
);
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
Object
element
=
Array
.
get
(
array
,
i
);
Object
element
=
Array
.
get
(
array
,
i
);
if
(
element
!=
null
)
{
if
(
element
!=
null
)
{
unknownFields
.
add
(
writeData
(
element
));
size
+=
computeSingularSerializedSize
(
Array
.
get
(
array
,
i
));
}
}
}
}
return
size
;
}
protected
int
computeSingularSerializedSize
(
Object
value
)
{
// This implementation is for message/group extensions.
int
fieldNumber
=
WireFormatNano
.
getTagFieldNumber
(
tag
);
switch
(
type
)
{
case
TYPE_GROUP:
MessageNano
groupValue
=
(
MessageNano
)
value
;
return
CodedOutputByteBufferNano
.
computeGroupSize
(
fieldNumber
,
groupValue
);
case
TYPE_MESSAGE:
MessageNano
messageValue
=
(
MessageNano
)
value
;
return
CodedOutputByteBufferNano
.
computeMessageSize
(
fieldNumber
,
messageValue
);
default
:
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
}
}
}
/**
/**
...
@@ -338,15 +335,6 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -338,15 +335,6 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
this
.
packedTag
=
packedTag
;
this
.
packedTag
=
packedTag
;
}
}
@Override
protected
boolean
isMatch
(
int
unknownDataTag
)
{
if
(
repeated
)
{
return
unknownDataTag
==
nonPackedTag
||
unknownDataTag
==
packedTag
;
}
else
{
return
unknownDataTag
==
tag
;
}
}
@Override
@Override
protected
Object
readData
(
CodedInputByteBufferNano
input
)
{
protected
Object
readData
(
CodedInputByteBufferNano
input
)
{
try
{
try
{
...
@@ -398,7 +386,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -398,7 +386,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
if
(
data
.
tag
==
nonPackedTag
)
{
if
(
data
.
tag
==
nonPackedTag
)
{
resultList
.
add
(
readData
(
CodedInputByteBufferNano
.
newInstance
(
data
.
bytes
)));
resultList
.
add
(
readData
(
CodedInputByteBufferNano
.
newInstance
(
data
.
bytes
)));
}
else
{
}
else
{
CodedInputByteBufferNano
buffer
=
CodedInputByteBufferNano
.
newInstance
(
data
.
bytes
);
CodedInputByteBufferNano
buffer
=
CodedInputByteBufferNano
.
newInstance
(
data
.
bytes
);
try
{
try
{
buffer
.
pushLimit
(
buffer
.
readRawVarint32
());
// length limit
buffer
.
pushLimit
(
buffer
.
readRawVarint32
());
// length limit
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
...
@@ -411,105 +400,73 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -411,105 +400,73 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
}
}
@Override
@Override
protected
final
UnknownFieldData
writeData
(
Object
value
)
{
protected
final
void
writeSingularData
(
Object
value
,
CodedOutputByteBufferNano
output
)
{
byte
[]
data
;
try
{
try
{
output
.
writeRawVarint32
(
tag
);
switch
(
type
)
{
switch
(
type
)
{
case
TYPE_DOUBLE:
case
TYPE_DOUBLE:
Double
doubleValue
=
(
Double
)
value
;
Double
doubleValue
=
(
Double
)
value
;
data
=
new
byte
[
output
.
writeDoubleNoTag
(
doubleValue
);
CodedOutputByteBufferNano
.
computeDoubleSizeNoTag
(
doubleValue
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeDoubleNoTag
(
doubleValue
);
break
;
break
;
case
TYPE_FLOAT:
case
TYPE_FLOAT:
Float
floatValue
=
(
Float
)
value
;
Float
floatValue
=
(
Float
)
value
;
data
=
new
byte
[
output
.
writeFloatNoTag
(
floatValue
);
CodedOutputByteBufferNano
.
computeFloatSizeNoTag
(
floatValue
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeFloatNoTag
(
floatValue
);
break
;
break
;
case
TYPE_INT64:
case
TYPE_INT64:
Long
int64Value
=
(
Long
)
value
;
Long
int64Value
=
(
Long
)
value
;
data
=
new
byte
[
output
.
writeInt64NoTag
(
int64Value
);
CodedOutputByteBufferNano
.
computeInt64SizeNoTag
(
int64Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeInt64NoTag
(
int64Value
);
break
;
break
;
case
TYPE_UINT64:
case
TYPE_UINT64:
Long
uint64Value
=
(
Long
)
value
;
Long
uint64Value
=
(
Long
)
value
;
data
=
new
byte
[
output
.
writeUInt64NoTag
(
uint64Value
);
CodedOutputByteBufferNano
.
computeUInt64SizeNoTag
(
uint64Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeUInt64NoTag
(
uint64Value
);
break
;
break
;
case
TYPE_INT32:
case
TYPE_INT32:
Integer
int32Value
=
(
Integer
)
value
;
Integer
int32Value
=
(
Integer
)
value
;
data
=
new
byte
[
output
.
writeInt32NoTag
(
int32Value
);
CodedOutputByteBufferNano
.
computeInt32SizeNoTag
(
int32Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeInt32NoTag
(
int32Value
);
break
;
break
;
case
TYPE_FIXED64:
case
TYPE_FIXED64:
Long
fixed64Value
=
(
Long
)
value
;
Long
fixed64Value
=
(
Long
)
value
;
data
=
new
byte
[
output
.
writeFixed64NoTag
(
fixed64Value
);
CodedOutputByteBufferNano
.
computeFixed64SizeNoTag
(
fixed64Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeFixed64NoTag
(
fixed64Value
);
break
;
break
;
case
TYPE_FIXED32:
case
TYPE_FIXED32:
Integer
fixed32Value
=
(
Integer
)
value
;
Integer
fixed32Value
=
(
Integer
)
value
;
data
=
new
byte
[
output
.
writeFixed32NoTag
(
fixed32Value
);
CodedOutputByteBufferNano
.
computeFixed32SizeNoTag
(
fixed32Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeFixed32NoTag
(
fixed32Value
);
break
;
break
;
case
TYPE_BOOL:
case
TYPE_BOOL:
Boolean
boolValue
=
(
Boolean
)
value
;
Boolean
boolValue
=
(
Boolean
)
value
;
data
=
new
byte
[
CodedOutputByteBufferNano
.
computeBoolSizeNoTag
(
boolValue
)];
output
.
writeBoolNoTag
(
boolValue
);
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeBoolNoTag
(
boolValue
);
break
;
break
;
case
TYPE_STRING:
case
TYPE_STRING:
String
stringValue
=
(
String
)
value
;
String
stringValue
=
(
String
)
value
;
data
=
new
byte
[
output
.
writeStringNoTag
(
stringValue
);
CodedOutputByteBufferNano
.
computeStringSizeNoTag
(
stringValue
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeStringNoTag
(
stringValue
);
break
;
break
;
case
TYPE_BYTES:
case
TYPE_BYTES:
byte
[]
bytesValue
=
(
byte
[])
value
;
byte
[]
bytesValue
=
(
byte
[])
value
;
data
=
new
byte
[
output
.
writeBytesNoTag
(
bytesValue
);
CodedOutputByteBufferNano
.
computeBytesSizeNoTag
(
bytesValue
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeBytesNoTag
(
bytesValue
);
break
;
break
;
case
TYPE_UINT32:
case
TYPE_UINT32:
Integer
uint32Value
=
(
Integer
)
value
;
Integer
uint32Value
=
(
Integer
)
value
;
data
=
new
byte
[
output
.
writeUInt32NoTag
(
uint32Value
);
CodedOutputByteBufferNano
.
computeUInt32SizeNoTag
(
uint32Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeUInt32NoTag
(
uint32Value
);
break
;
break
;
case
TYPE_ENUM:
case
TYPE_ENUM:
Integer
enumValue
=
(
Integer
)
value
;
Integer
enumValue
=
(
Integer
)
value
;
data
=
new
byte
[
CodedOutputByteBufferNano
.
computeEnumSizeNoTag
(
enumValue
)];
output
.
writeEnumNoTag
(
enumValue
);
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeEnumNoTag
(
enumValue
);
break
;
break
;
case
TYPE_SFIXED32:
case
TYPE_SFIXED32:
Integer
sfixed32Value
=
(
Integer
)
value
;
Integer
sfixed32Value
=
(
Integer
)
value
;
data
=
new
byte
[
output
.
writeSFixed32NoTag
(
sfixed32Value
);
CodedOutputByteBufferNano
.
computeSFixed32SizeNoTag
(
sfixed32Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
)
.
writeSFixed32NoTag
(
sfixed32Value
);
break
;
break
;
case
TYPE_SFIXED64:
case
TYPE_SFIXED64:
Long
sfixed64Value
=
(
Long
)
value
;
Long
sfixed64Value
=
(
Long
)
value
;
data
=
new
byte
[
output
.
writeSFixed64NoTag
(
sfixed64Value
);
CodedOutputByteBufferNano
.
computeSFixed64SizeNoTag
(
sfixed64Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
)
.
writeSFixed64NoTag
(
sfixed64Value
);
break
;
break
;
case
TYPE_SINT32:
case
TYPE_SINT32:
Integer
sint32Value
=
(
Integer
)
value
;
Integer
sint32Value
=
(
Integer
)
value
;
data
=
new
byte
[
output
.
writeSInt32NoTag
(
sint32Value
);
CodedOutputByteBufferNano
.
computeSInt32SizeNoTag
(
sint32Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeSInt32NoTag
(
sint32Value
);
break
;
break
;
case
TYPE_SINT64:
case
TYPE_SINT64:
Long
sint64Value
=
(
Long
)
value
;
Long
sint64Value
=
(
Long
)
value
;
data
=
new
byte
[
output
.
writeSInt64NoTag
(
sint64Value
);
CodedOutputByteBufferNano
.
computeSInt64SizeNoTag
(
sint64Value
)];
CodedOutputByteBufferNano
.
newInstance
(
data
).
writeSInt64NoTag
(
sint64Value
);
break
;
break
;
default
:
default
:
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
...
@@ -518,86 +475,21 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -518,86 +475,21 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
// Should not happen
// Should not happen
throw
new
IllegalStateException
(
e
);
throw
new
IllegalStateException
(
e
);
}
}
return
new
UnknownFieldData
(
tag
,
data
);
}
}
@Override
@Override
protected
void
write
DataInto
(
T
array
,
List
<
UnknownFieldData
>
unknownFields
)
{
protected
void
write
RepeatedData
(
Object
array
,
CodedOutputByteBufferNano
output
)
{
if
(
tag
==
nonPackedTag
)
{
if
(
tag
==
nonPackedTag
)
{
// Use base implementation for non-packed data
// Use base implementation for non-packed data
super
.
write
DataInto
(
array
,
unknownFields
);
super
.
write
RepeatedData
(
array
,
output
);
}
else
if
(
tag
==
packedTag
)
{
}
else
if
(
tag
==
packedTag
)
{
// Packed. Note that the array element type is guaranteed to be primitive, so there
// Packed. Note that the array element type is guaranteed to be primitive, so there
// won't be any null elements, so no null check in this block.
First get data size.
// won't be any null elements, so no null check in this block.
int
arrayLength
=
Array
.
getLength
(
array
);
int
arrayLength
=
Array
.
getLength
(
array
);
int
dataSize
=
0
;
int
dataSize
=
computePackedDataSize
(
array
);
switch
(
type
)
{
case
TYPE_BOOL:
// Bools are stored as int32 but just as 0 or 1, so 1 byte each.
dataSize
=
arrayLength
;
break
;
case
TYPE_FIXED32:
case
TYPE_SFIXED32:
case
TYPE_FLOAT:
dataSize
=
arrayLength
*
CodedOutputByteBufferNano
.
LITTLE_ENDIAN_32_SIZE
;
break
;
case
TYPE_FIXED64:
case
TYPE_SFIXED64:
case
TYPE_DOUBLE:
dataSize
=
arrayLength
*
CodedOutputByteBufferNano
.
LITTLE_ENDIAN_64_SIZE
;
break
;
case
TYPE_INT32:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeInt32SizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
case
TYPE_SINT32:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeSInt32SizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
case
TYPE_UINT32:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeUInt32SizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
case
TYPE_INT64:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeInt64SizeNoTag
(
Array
.
getLong
(
array
,
i
));
}
break
;
case
TYPE_SINT64:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeSInt64SizeNoTag
(
Array
.
getLong
(
array
,
i
));
}
break
;
case
TYPE_UINT64:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeUInt64SizeNoTag
(
Array
.
getLong
(
array
,
i
));
}
break
;
case
TYPE_ENUM:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeEnumSizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
default
:
throw
new
IllegalArgumentException
(
"Unexpected non-packable type "
+
type
);
}
// Then construct payload.
int
payloadSize
=
dataSize
+
CodedOutputByteBufferNano
.
computeRawVarint32Size
(
dataSize
);
byte
[]
data
=
new
byte
[
payloadSize
];
CodedOutputByteBufferNano
output
=
CodedOutputByteBufferNano
.
newInstance
(
data
);
try
{
try
{
output
.
writeRawVarint32
(
tag
);
output
.
writeRawVarint32
(
dataSize
);
output
.
writeRawVarint32
(
dataSize
);
switch
(
type
)
{
switch
(
type
)
{
case
TYPE_BOOL:
case
TYPE_BOOL:
...
@@ -677,12 +569,154 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
...
@@ -677,12 +569,154 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
// Should not happen.
// Should not happen.
throw
new
IllegalStateException
(
e
);
throw
new
IllegalStateException
(
e
);
}
}
unknownFields
.
add
(
new
UnknownFieldData
(
tag
,
data
));
}
else
{
}
else
{
throw
new
IllegalArgumentException
(
"Unexpected repeated extension tag "
+
tag
throw
new
IllegalArgumentException
(
"Unexpected repeated extension tag "
+
tag
+
", unequal to both non-packed variant "
+
nonPackedTag
+
", unequal to both non-packed variant "
+
nonPackedTag
+
" and packed variant "
+
packedTag
);
+
" and packed variant "
+
packedTag
);
}
}
}
}
private
int
computePackedDataSize
(
Object
array
)
{
int
dataSize
=
0
;
int
arrayLength
=
Array
.
getLength
(
array
);
switch
(
type
)
{
case
TYPE_BOOL:
// Bools are stored as int32 but just as 0 or 1, so 1 byte each.
dataSize
=
arrayLength
;
break
;
case
TYPE_FIXED32:
case
TYPE_SFIXED32:
case
TYPE_FLOAT:
dataSize
=
arrayLength
*
CodedOutputByteBufferNano
.
LITTLE_ENDIAN_32_SIZE
;
break
;
case
TYPE_FIXED64:
case
TYPE_SFIXED64:
case
TYPE_DOUBLE:
dataSize
=
arrayLength
*
CodedOutputByteBufferNano
.
LITTLE_ENDIAN_64_SIZE
;
break
;
case
TYPE_INT32:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeInt32SizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
case
TYPE_SINT32:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeSInt32SizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
case
TYPE_UINT32:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeUInt32SizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
case
TYPE_INT64:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeInt64SizeNoTag
(
Array
.
getLong
(
array
,
i
));
}
break
;
case
TYPE_SINT64:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeSInt64SizeNoTag
(
Array
.
getLong
(
array
,
i
));
}
break
;
case
TYPE_UINT64:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeUInt64SizeNoTag
(
Array
.
getLong
(
array
,
i
));
}
break
;
case
TYPE_ENUM:
for
(
int
i
=
0
;
i
<
arrayLength
;
i
++)
{
dataSize
+=
CodedOutputByteBufferNano
.
computeEnumSizeNoTag
(
Array
.
getInt
(
array
,
i
));
}
break
;
default
:
throw
new
IllegalArgumentException
(
"Unexpected non-packable type "
+
type
);
}
return
dataSize
;
}
@Override
protected
int
computeRepeatedSerializedSize
(
Object
array
)
{
if
(
tag
==
nonPackedTag
)
{
// Use base implementation for non-packed data
return
super
.
computeRepeatedSerializedSize
(
array
);
}
else
if
(
tag
==
packedTag
)
{
// Packed.
int
dataSize
=
computePackedDataSize
(
array
);
int
payloadSize
=
dataSize
+
CodedOutputByteBufferNano
.
computeRawVarint32Size
(
dataSize
);
return
payloadSize
+
CodedOutputByteBufferNano
.
computeRawVarint32Size
(
tag
);
}
else
{
throw
new
IllegalArgumentException
(
"Unexpected repeated extension tag "
+
tag
+
", unequal to both non-packed variant "
+
nonPackedTag
+
" and packed variant "
+
packedTag
);
}
}
@Override
protected
final
int
computeSingularSerializedSize
(
Object
value
)
{
int
fieldNumber
=
WireFormatNano
.
getTagFieldNumber
(
tag
);
switch
(
type
)
{
case
TYPE_DOUBLE:
Double
doubleValue
=
(
Double
)
value
;
return
CodedOutputByteBufferNano
.
computeDoubleSize
(
fieldNumber
,
doubleValue
);
case
TYPE_FLOAT:
Float
floatValue
=
(
Float
)
value
;
return
CodedOutputByteBufferNano
.
computeFloatSize
(
fieldNumber
,
floatValue
);
case
TYPE_INT64:
Long
int64Value
=
(
Long
)
value
;
return
CodedOutputByteBufferNano
.
computeInt64Size
(
fieldNumber
,
int64Value
);
case
TYPE_UINT64:
Long
uint64Value
=
(
Long
)
value
;
return
CodedOutputByteBufferNano
.
computeUInt64Size
(
fieldNumber
,
uint64Value
);
case
TYPE_INT32:
Integer
int32Value
=
(
Integer
)
value
;
return
CodedOutputByteBufferNano
.
computeInt32Size
(
fieldNumber
,
int32Value
);
case
TYPE_FIXED64:
Long
fixed64Value
=
(
Long
)
value
;
return
CodedOutputByteBufferNano
.
computeFixed64Size
(
fieldNumber
,
fixed64Value
);
case
TYPE_FIXED32:
Integer
fixed32Value
=
(
Integer
)
value
;
return
CodedOutputByteBufferNano
.
computeFixed32Size
(
fieldNumber
,
fixed32Value
);
case
TYPE_BOOL:
Boolean
boolValue
=
(
Boolean
)
value
;
return
CodedOutputByteBufferNano
.
computeBoolSize
(
fieldNumber
,
boolValue
);
case
TYPE_STRING:
String
stringValue
=
(
String
)
value
;
return
CodedOutputByteBufferNano
.
computeStringSize
(
fieldNumber
,
stringValue
);
case
TYPE_BYTES:
byte
[]
bytesValue
=
(
byte
[])
value
;
return
CodedOutputByteBufferNano
.
computeBytesSize
(
fieldNumber
,
bytesValue
);
case
TYPE_UINT32:
Integer
uint32Value
=
(
Integer
)
value
;
return
CodedOutputByteBufferNano
.
computeUInt32Size
(
fieldNumber
,
uint32Value
);
case
TYPE_ENUM:
Integer
enumValue
=
(
Integer
)
value
;
return
CodedOutputByteBufferNano
.
computeEnumSize
(
fieldNumber
,
enumValue
);
case
TYPE_SFIXED32:
Integer
sfixed32Value
=
(
Integer
)
value
;
return
CodedOutputByteBufferNano
.
computeSFixed32Size
(
fieldNumber
,
sfixed32Value
);
case
TYPE_SFIXED64:
Long
sfixed64Value
=
(
Long
)
value
;
return
CodedOutputByteBufferNano
.
computeSFixed64Size
(
fieldNumber
,
sfixed64Value
);
case
TYPE_SINT32:
Integer
sint32Value
=
(
Integer
)
value
;
return
CodedOutputByteBufferNano
.
computeSInt32Size
(
fieldNumber
,
sint32Value
);
case
TYPE_SINT64:
Long
sint64Value
=
(
Long
)
value
;
return
CodedOutputByteBufferNano
.
computeSInt64Size
(
fieldNumber
,
sint64Value
);
default
:
throw
new
IllegalArgumentException
(
"Unknown type "
+
type
);
}
}
}
}
}
}
java/src/main/java/com/google/protobuf/nano/FieldArray.java
0 → 100644
View file @
30b1454d
// Protocol Buffers - Google's data interchange format
// Copyright 2014 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.
package
com
.
google
.
protobuf
.
nano
;
/**
* A custom version of {@link android.util.SparseArray} with the minimal API
* for storing {@link FieldData} objects.
*
* Based on {@link android.support.v4.util.SpareArrayCompat}.
*/
class
FieldArray
{
private
static
final
FieldData
DELETED
=
new
FieldData
();
private
boolean
mGarbage
=
false
;
private
int
[]
mFieldNumbers
;
private
FieldData
[]
mData
;
private
int
mSize
;
/**
* Creates a new FieldArray containing no fields.
*/
public
FieldArray
()
{
this
(
10
);
}
/**
* Creates a new FieldArray containing no mappings that will not
* require any additional memory allocation to store the specified
* number of mappings.
*/
public
FieldArray
(
int
initialCapacity
)
{
initialCapacity
=
idealIntArraySize
(
initialCapacity
);
mFieldNumbers
=
new
int
[
initialCapacity
];
mData
=
new
FieldData
[
initialCapacity
];
mSize
=
0
;
}
/**
* Gets the FieldData mapped from the specified fieldNumber, or <code>null</code>
* if no such mapping has been made.
*/
public
FieldData
get
(
int
fieldNumber
)
{
int
i
=
binarySearch
(
fieldNumber
);
if
(
i
<
0
||
mData
[
i
]
==
DELETED
)
{
return
null
;
}
else
{
return
mData
[
i
];
}
}
/**
* Removes the data from the specified fieldNumber, if there was any.
*/
public
void
remove
(
int
fieldNumber
)
{
int
i
=
binarySearch
(
fieldNumber
);
if
(
i
>=
0
&&
mData
[
i
]
!=
DELETED
)
{
mData
[
i
]
=
DELETED
;
mGarbage
=
true
;
}
}
private
void
gc
()
{
int
n
=
mSize
;
int
o
=
0
;
int
[]
keys
=
mFieldNumbers
;
FieldData
[]
values
=
mData
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
FieldData
val
=
values
[
i
];
if
(
val
!=
DELETED
)
{
if
(
i
!=
o
)
{
keys
[
o
]
=
keys
[
i
];
values
[
o
]
=
val
;
values
[
i
]
=
null
;
}
o
++;
}
}
mGarbage
=
false
;
mSize
=
o
;
}
/**
* Adds a mapping from the specified fieldNumber to the specified data,
* replacing the previous mapping if there was one.
*/
public
void
put
(
int
fieldNumber
,
FieldData
data
)
{
int
i
=
binarySearch
(
fieldNumber
);
if
(
i
>=
0
)
{
mData
[
i
]
=
data
;
}
else
{
i
=
~
i
;
if
(
i
<
mSize
&&
mData
[
i
]
==
DELETED
)
{
mFieldNumbers
[
i
]
=
fieldNumber
;
mData
[
i
]
=
data
;
return
;
}
if
(
mGarbage
&&
mSize
>=
mFieldNumbers
.
length
)
{
gc
();
// Search again because indices may have changed.
i
=
~
binarySearch
(
fieldNumber
);
}
if
(
mSize
>=
mFieldNumbers
.
length
)
{
int
n
=
idealIntArraySize
(
mSize
+
1
);
int
[]
nkeys
=
new
int
[
n
];
FieldData
[]
nvalues
=
new
FieldData
[
n
];
System
.
arraycopy
(
mFieldNumbers
,
0
,
nkeys
,
0
,
mFieldNumbers
.
length
);
System
.
arraycopy
(
mData
,
0
,
nvalues
,
0
,
mData
.
length
);
mFieldNumbers
=
nkeys
;
mData
=
nvalues
;
}
if
(
mSize
-
i
!=
0
)
{
System
.
arraycopy
(
mFieldNumbers
,
i
,
mFieldNumbers
,
i
+
1
,
mSize
-
i
);
System
.
arraycopy
(
mData
,
i
,
mData
,
i
+
1
,
mSize
-
i
);
}
mFieldNumbers
[
i
]
=
fieldNumber
;
mData
[
i
]
=
data
;
mSize
++;
}
}
/**
* Returns the number of key-value mappings that this FieldArray
* currently stores.
*/
public
int
size
()
{
if
(
mGarbage
)
{
gc
();
}
return
mSize
;
}
public
boolean
isEmpty
()
{
return
size
()
==
0
;
}
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the value from the <code>index</code>th key-value mapping that this
* FieldArray stores.
*/
public
FieldData
dataAt
(
int
index
)
{
if
(
mGarbage
)
{
gc
();
}
return
mData
[
index
];
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
o
==
this
)
{
return
true
;
}
if
(!(
o
instanceof
FieldArray
))
{
return
false
;
}
FieldArray
other
=
(
FieldArray
)
o
;
if
(
size
()
!=
other
.
size
())
{
// size() will call gc() if necessary.
return
false
;
}
return
arrayEquals
(
mFieldNumbers
,
other
.
mFieldNumbers
,
mSize
)
&&
arrayEquals
(
mData
,
other
.
mData
,
mSize
);
}
@Override
public
int
hashCode
()
{
if
(
mGarbage
)
{
gc
();
}
int
result
=
17
;
for
(
int
i
=
0
;
i
<
mSize
;
i
++)
{
result
=
31
*
result
+
mFieldNumbers
[
i
];
result
=
31
*
result
+
mData
[
i
].
hashCode
();
}
return
result
;
}
private
int
idealIntArraySize
(
int
need
)
{
return
idealByteArraySize
(
need
*
4
)
/
4
;
}
private
int
idealByteArraySize
(
int
need
)
{
for
(
int
i
=
4
;
i
<
32
;
i
++)
if
(
need
<=
(
1
<<
i
)
-
12
)
return
(
1
<<
i
)
-
12
;
return
need
;
}
private
int
binarySearch
(
int
value
)
{
int
lo
=
0
;
int
hi
=
mSize
-
1
;
while
(
lo
<=
hi
)
{
int
mid
=
(
lo
+
hi
)
>>>
1
;
int
midVal
=
mFieldNumbers
[
mid
];
if
(
midVal
<
value
)
{
lo
=
mid
+
1
;
}
else
if
(
midVal
>
value
)
{
hi
=
mid
-
1
;
}
else
{
return
mid
;
// value found
}
}
return
~
lo
;
// value not present
}
private
boolean
arrayEquals
(
int
[]
a
,
int
[]
b
,
int
size
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
return
false
;
}
}
return
true
;
}
private
boolean
arrayEquals
(
FieldData
[]
a
,
FieldData
[]
b
,
int
size
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
(!
a
[
i
].
equals
(
b
[
i
]))
{
return
false
;
}
}
return
true
;
}
}
java/src/main/java/com/google/protobuf/nano/FieldData.java
0 → 100644
View file @
30b1454d
// Protocol Buffers - Google's data interchange format
// Copyright 2014 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.
package
com
.
google
.
protobuf
.
nano
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
/**
* Stores unknown fields. These might be extensions or fields that the generated API doesn't
* know about yet.
*/
class
FieldData
{
private
Extension
<?,
?>
cachedExtension
;
private
Object
value
;
/** The serialised values for this object. Will be cleared if getValue is called */
private
List
<
UnknownFieldData
>
unknownFieldData
;
<
T
>
FieldData
(
Extension
<?,
T
>
extension
,
T
newValue
)
{
cachedExtension
=
extension
;
value
=
newValue
;
}
FieldData
()
{
unknownFieldData
=
new
ArrayList
<
UnknownFieldData
>();
}
void
addUnknownField
(
UnknownFieldData
unknownField
)
{
unknownFieldData
.
add
(
unknownField
);
}
<
T
>
T
getValue
(
Extension
<?,
T
>
extension
)
{
if
(
value
!=
null
){
if
(
cachedExtension
!=
extension
)
{
// Extension objects are singletons.
throw
new
IllegalStateException
(
"Tried to getExtension with a differernt Extension."
);
}
}
else
{
cachedExtension
=
extension
;
value
=
extension
.
getValueFrom
(
unknownFieldData
);
unknownFieldData
=
null
;
}
return
(
T
)
value
;
}
<
T
>
void
setValue
(
Extension
<?,
T
>
extension
,
T
newValue
)
{
cachedExtension
=
extension
;
value
=
newValue
;
unknownFieldData
=
null
;
}
int
computeSerializedSize
()
{
int
size
=
0
;
if
(
value
!=
null
)
{
size
=
cachedExtension
.
computeSerializedSize
(
value
);
}
else
{
for
(
UnknownFieldData
unknownField
:
unknownFieldData
)
{
size
+=
unknownField
.
computeSerializedSize
();
}
}
return
size
;
}
void
writeTo
(
CodedOutputByteBufferNano
output
)
throws
IOException
{
if
(
value
!=
null
)
{
cachedExtension
.
writeTo
(
value
,
output
);
}
else
{
for
(
UnknownFieldData
unknownField
:
unknownFieldData
)
{
unknownField
.
writeTo
(
output
);
}
}
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
o
==
this
)
{
return
true
;
}
if
(!(
o
instanceof
FieldData
))
{
return
false
;
}
FieldData
other
=
(
FieldData
)
o
;
if
(
value
!=
null
&&
other
.
value
!=
null
)
{
// If both objects have deserialized values, compare those.
// Since unknown fields are only compared if messages have generated equals methods
// we know this will be a meaningful comparison (not identity) for all values.
if
(
cachedExtension
!=
other
.
cachedExtension
)
{
// Extension objects are singletons.
return
false
;
}
if
(!
cachedExtension
.
clazz
.
isArray
())
{
// Can't test (!cachedExtension.repeated) due to 'bytes' -> 'byte[]'
return
value
.
equals
(
other
.
value
);
}
if
(
value
instanceof
byte
[])
{
return
Arrays
.
equals
((
byte
[])
value
,
(
byte
[])
other
.
value
);
}
else
if
(
value
instanceof
int
[])
{
return
Arrays
.
equals
((
int
[])
value
,
(
int
[])
other
.
value
);
}
else
if
(
value
instanceof
long
[])
{
return
Arrays
.
equals
((
long
[])
value
,
(
long
[])
other
.
value
);
}
else
if
(
value
instanceof
float
[])
{
return
Arrays
.
equals
((
float
[])
value
,
(
float
[])
other
.
value
);
}
else
if
(
value
instanceof
double
[])
{
return
Arrays
.
equals
((
double
[])
value
,
(
double
[])
other
.
value
);
}
else
if
(
value
instanceof
boolean
[])
{
return
Arrays
.
equals
((
boolean
[])
value
,
(
boolean
[])
other
.
value
);
}
else
{
return
Arrays
.
deepEquals
((
Object
[])
value
,
(
Object
[])
other
.
value
);
}
}
if
(
unknownFieldData
!=
null
&&
other
.
unknownFieldData
!=
null
)
{
// If both objects have byte arrays compare those directly.
return
unknownFieldData
.
equals
(
other
.
unknownFieldData
);
}
try
{
// As a last resort, serialize and compare the resulting byte arrays.
return
Arrays
.
equals
(
toByteArray
(),
other
.
toByteArray
());
}
catch
(
IOException
e
)
{
// Should not happen.
throw
new
IllegalStateException
(
e
);
}
}
@Override
public
int
hashCode
()
{
int
result
=
17
;
try
{
// The only way to generate a consistent hash is to use the serialized form.
result
=
31
*
result
+
Arrays
.
hashCode
(
toByteArray
());
}
catch
(
IOException
e
)
{
// Should not happen.
throw
new
IllegalStateException
(
e
);
}
return
result
;
}
private
byte
[]
toByteArray
()
throws
IOException
{
byte
[]
result
=
new
byte
[
computeSerializedSize
()];
CodedOutputByteBufferNano
output
=
CodedOutputByteBufferNano
.
newInstance
(
result
);
writeTo
(
output
);
return
result
;
}
}
java/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
View file @
30b1454d
...
@@ -30,42 +30,55 @@
...
@@ -30,42 +30,55 @@
package
com
.
google
.
protobuf
.
nano
;
package
com
.
google
.
protobuf
.
nano
;
import
java.io.IOException
;
import
java.util.Arrays
;
import
java.util.Arrays
;
/**
/**
* Stores unknown fields. These might be extensions or fields that the generated
API doesn't
* Stores unknown fields. These might be extensions or fields that the generated
* know about yet.
*
API doesn't
know about yet.
*
*
* @author bduff@google.com (Brian Duff)
* @author bduff@google.com (Brian Duff)
*/
*/
public
final
class
UnknownFieldData
{
final
class
UnknownFieldData
{
final
int
tag
;
final
int
tag
;
final
byte
[]
bytes
;
final
byte
[]
bytes
;
UnknownFieldData
(
int
tag
,
byte
[]
bytes
)
{
UnknownFieldData
(
int
tag
,
byte
[]
bytes
)
{
this
.
tag
=
tag
;
this
.
tag
=
tag
;
this
.
bytes
=
bytes
;
this
.
bytes
=
bytes
;
}
}
@Override
int
computeSerializedSize
()
{
public
boolean
equals
(
Object
o
)
{
int
size
=
0
;
if
(
o
==
this
)
{
size
+=
CodedOutputByteBufferNano
.
computeRawVarint32Size
(
tag
);
return
true
;
size
+=
bytes
.
length
;
return
size
;
}
}
if
(!(
o
instanceof
UnknownFieldData
))
{
return
false
;
void
writeTo
(
CodedOutputByteBufferNano
output
)
throws
IOException
{
output
.
writeRawVarint32
(
tag
);
output
.
writeRawBytes
(
bytes
);
}
}
UnknownFieldData
other
=
(
UnknownFieldData
)
o
;
@Override
return
tag
==
other
.
tag
&&
Arrays
.
equals
(
bytes
,
other
.
bytes
);
public
boolean
equals
(
Object
o
)
{
}
if
(
o
==
this
)
{
return
true
;
}
if
(!(
o
instanceof
UnknownFieldData
))
{
return
false
;
}
@Override
UnknownFieldData
other
=
(
UnknownFieldData
)
o
;
public
int
hashCode
()
{
return
tag
==
other
.
tag
&&
Arrays
.
equals
(
bytes
,
other
.
bytes
);
int
result
=
17
;
}
result
=
31
*
result
+
tag
;
result
=
31
*
result
+
Arrays
.
hashCode
(
bytes
);
@Override
return
result
;
public
int
hashCode
()
{
}
int
result
=
17
;
result
=
31
*
result
+
tag
;
result
=
31
*
result
+
Arrays
.
hashCode
(
bytes
);
return
result
;
}
}
}
java/src/test/java/com/google/protobuf/NanoTest.java
View file @
30b1454d
...
@@ -41,6 +41,7 @@ import com.google.protobuf.nano.Extensions.MessageWithGroup;
...
@@ -41,6 +41,7 @@ import com.google.protobuf.nano.Extensions.MessageWithGroup;
import
com.google.protobuf.nano.FileScopeEnumMultiple
;
import
com.google.protobuf.nano.FileScopeEnumMultiple
;
import
com.google.protobuf.nano.FileScopeEnumRefNano
;
import
com.google.protobuf.nano.FileScopeEnumRefNano
;
import
com.google.protobuf.nano.InternalNano
;
import
com.google.protobuf.nano.InternalNano
;
import
com.google.protobuf.nano.InvalidProtocolBufferNanoException
;
import
com.google.protobuf.nano.MessageNano
;
import
com.google.protobuf.nano.MessageNano
;
import
com.google.protobuf.nano.MessageScopeEnumRefNano
;
import
com.google.protobuf.nano.MessageScopeEnumRefNano
;
import
com.google.protobuf.nano.MultipleImportingNonMultipleNano1
;
import
com.google.protobuf.nano.MultipleImportingNonMultipleNano1
;
...
@@ -2826,6 +2827,8 @@ public class NanoTest extends TestCase {
...
@@ -2826,6 +2827,8 @@ public class NanoTest extends TestCase {
assertEquals
(
group2
.
a
,
message
.
getExtension
(
SingularExtensions
.
someGroup
).
a
);
assertEquals
(
group2
.
a
,
message
.
getExtension
(
SingularExtensions
.
someGroup
).
a
);
// Test reading back using RepeatedExtensions: the arrays should be equal.
// Test reading back using RepeatedExtensions: the arrays should be equal.
message
=
Extensions
.
ExtendableMessage
.
parseFrom
(
data
);
assertEquals
(
5
,
message
.
field
);
assertTrue
(
Arrays
.
equals
(
int32s
,
message
.
getExtension
(
RepeatedExtensions
.
repeatedInt32
)));
assertTrue
(
Arrays
.
equals
(
int32s
,
message
.
getExtension
(
RepeatedExtensions
.
repeatedInt32
)));
assertTrue
(
Arrays
.
equals
(
uint32s
,
message
.
getExtension
(
RepeatedExtensions
.
repeatedUint32
)));
assertTrue
(
Arrays
.
equals
(
uint32s
,
message
.
getExtension
(
RepeatedExtensions
.
repeatedUint32
)));
assertTrue
(
Arrays
.
equals
(
sint32s
,
message
.
getExtension
(
RepeatedExtensions
.
repeatedSint32
)));
assertTrue
(
Arrays
.
equals
(
sint32s
,
message
.
getExtension
(
RepeatedExtensions
.
repeatedSint32
)));
...
@@ -2860,6 +2863,8 @@ public class NanoTest extends TestCase {
...
@@ -2860,6 +2863,8 @@ public class NanoTest extends TestCase {
// Test reading back using PackedExtensions: the arrays should be equal, even the fields
// Test reading back using PackedExtensions: the arrays should be equal, even the fields
// are non-packed.
// are non-packed.
message
=
Extensions
.
ExtendableMessage
.
parseFrom
(
data
);
assertEquals
(
5
,
message
.
field
);
assertTrue
(
Arrays
.
equals
(
int32s
,
message
.
getExtension
(
PackedExtensions
.
packedInt32
)));
assertTrue
(
Arrays
.
equals
(
int32s
,
message
.
getExtension
(
PackedExtensions
.
packedInt32
)));
assertTrue
(
Arrays
.
equals
(
uint32s
,
message
.
getExtension
(
PackedExtensions
.
packedUint32
)));
assertTrue
(
Arrays
.
equals
(
uint32s
,
message
.
getExtension
(
PackedExtensions
.
packedUint32
)));
assertTrue
(
Arrays
.
equals
(
sint32s
,
message
.
getExtension
(
PackedExtensions
.
packedSint32
)));
assertTrue
(
Arrays
.
equals
(
sint32s
,
message
.
getExtension
(
PackedExtensions
.
packedSint32
)));
...
@@ -2924,6 +2929,138 @@ public class NanoTest extends TestCase {
...
@@ -2924,6 +2929,138 @@ public class NanoTest extends TestCase {
assertEquals
(
0
,
MessageNano
.
toByteArray
(
message
).
length
);
assertEquals
(
0
,
MessageNano
.
toByteArray
(
message
).
length
);
}
}
public
void
testExtensionsMutation
()
{
Extensions
.
ExtendableMessage
extendableMessage
=
new
Extensions
.
ExtendableMessage
();
extendableMessage
.
setExtension
(
SingularExtensions
.
someMessage
,
new
Extensions
.
AnotherMessage
());
extendableMessage
.
getExtension
(
SingularExtensions
.
someMessage
).
string
=
"not empty"
;
assertEquals
(
"not empty"
,
extendableMessage
.
getExtension
(
SingularExtensions
.
someMessage
).
string
);
}
public
void
testExtensionsMutation_Equals
()
throws
InvalidProtocolBufferNanoException
{
Extensions
.
ExtendableMessage
extendableMessage
=
new
Extensions
.
ExtendableMessage
();
extendableMessage
.
field
=
5
;
int
int32
=
42
;
int
[]
uint32s
=
{
3
,
4
};
int
[]
sint32s
=
{-
5
,
-
6
};
long
[]
int64s
=
{
7
,
8
};
long
[]
uint64s
=
{
9
,
10
};
long
[]
sint64s
=
{-
11
,
-
12
};
int
[]
fixed32s
=
{
13
,
14
};
int
[]
sfixed32s
=
{-
15
,
-
16
};
long
[]
fixed64s
=
{
17
,
18
};
long
[]
sfixed64s
=
{-
19
,
-
20
};
boolean
[]
bools
=
{
true
,
false
};
float
[]
floats
=
{
2.1f
,
2.2f
};
double
[]
doubles
=
{
2.3
,
2.4
};
int
[]
enums
=
{
Extensions
.
SECOND_VALUE
,
Extensions
.
FIRST_VALUE
};
String
[]
strings
=
{
"vijfentwintig"
,
"twenty-six"
};
byte
[][]
bytess
=
{{
2
,
7
},
{
2
,
8
}};
AnotherMessage
another1
=
new
AnotherMessage
();
another1
.
string
=
"er shi jiu"
;
another1
.
value
=
false
;
AnotherMessage
another2
=
new
AnotherMessage
();
another2
.
string
=
"trente"
;
another2
.
value
=
true
;
AnotherMessage
[]
messages
=
{
another1
,
another2
};
RepeatedExtensions
.
RepeatedGroup
group1
=
new
RepeatedExtensions
.
RepeatedGroup
();
group1
.
a
=
31
;
RepeatedExtensions
.
RepeatedGroup
group2
=
new
RepeatedExtensions
.
RepeatedGroup
();
group2
.
a
=
32
;
RepeatedExtensions
.
RepeatedGroup
[]
groups
=
{
group1
,
group2
};
extendableMessage
.
setExtension
(
SingularExtensions
.
someInt32
,
int32
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedUint32
,
uint32s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedSint32
,
sint32s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedInt64
,
int64s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedUint64
,
uint64s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedSint64
,
sint64s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedFixed32
,
fixed32s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedSfixed32
,
sfixed32s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedFixed64
,
fixed64s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedSfixed64
,
sfixed64s
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedBool
,
bools
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedFloat
,
floats
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedDouble
,
doubles
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedEnum
,
enums
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedString
,
strings
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedBytes
,
bytess
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedMessage
,
messages
);
extendableMessage
.
setExtension
(
RepeatedExtensions
.
repeatedGroup
,
groups
);
byte
[]
data
=
MessageNano
.
toByteArray
(
extendableMessage
);
extendableMessage
=
Extensions
.
ExtendableMessage
.
parseFrom
(
data
);
Extensions
.
ExtendableMessage
messageCopy
=
Extensions
.
ExtendableMessage
.
parseFrom
(
data
);
// Without deserialising.
assertEquals
(
extendableMessage
,
messageCopy
);
assertEquals
(
extendableMessage
.
hashCode
(),
messageCopy
.
hashCode
());
// Only one deserialized.
extendableMessage
.
getExtension
(
SingularExtensions
.
someInt32
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedUint32
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedSint32
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedInt64
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedUint64
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedSint64
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedFixed32
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedSfixed32
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedFixed64
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedSfixed64
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedBool
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedFloat
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedDouble
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedEnum
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedString
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedBytes
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedMessage
);
extendableMessage
.
getExtension
(
RepeatedExtensions
.
repeatedGroup
);
assertEquals
(
extendableMessage
,
messageCopy
);
assertEquals
(
extendableMessage
.
hashCode
(),
messageCopy
.
hashCode
());
// Both deserialized.
messageCopy
.
getExtension
(
SingularExtensions
.
someInt32
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedUint32
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedSint32
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedInt64
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedUint64
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedSint64
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedFixed32
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedSfixed32
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedFixed64
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedSfixed64
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedBool
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedFloat
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedDouble
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedEnum
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedString
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedBytes
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedMessage
);
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedGroup
);
assertEquals
(
extendableMessage
,
messageCopy
);
assertEquals
(
extendableMessage
.
hashCode
(),
messageCopy
.
hashCode
());
// Change one, make sure they are still different.
messageCopy
.
getExtension
(
RepeatedExtensions
.
repeatedMessage
)[
0
].
string
=
"not empty"
;
assertFalse
(
extendableMessage
.
equals
(
messageCopy
));
// Even if the extension hasn't been deserialized.
extendableMessage
=
Extensions
.
ExtendableMessage
.
parseFrom
(
data
);
assertFalse
(
extendableMessage
.
equals
(
messageCopy
));
}
public
void
testExtensionsCaching
()
{
Extensions
.
ExtendableMessage
extendableMessage
=
new
Extensions
.
ExtendableMessage
();
extendableMessage
.
setExtension
(
SingularExtensions
.
someMessage
,
new
Extensions
.
AnotherMessage
());
assertSame
(
"Consecutive calls to getExtensions should return the same object"
,
extendableMessage
.
getExtension
(
SingularExtensions
.
someMessage
),
extendableMessage
.
getExtension
(
SingularExtensions
.
someMessage
));
}
public
void
testUnknownFields
()
throws
Exception
{
public
void
testUnknownFields
()
throws
Exception
{
// Check that we roundtrip (serialize and deserialize) unrecognized fields.
// Check that we roundtrip (serialize and deserialize) unrecognized fields.
AnotherMessage
message
=
new
AnotherMessage
();
AnotherMessage
message
=
new
AnotherMessage
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment