Skip to content

Commit c5d3cb2

Browse files
committed
Fix #67
1 parent 5a61f50 commit c5d3cb2

File tree

4 files changed

+35
-28
lines changed

4 files changed

+35
-28
lines changed

protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ByteAccumulator.java

+19-13
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ public class ByteAccumulator
1919
protected final byte[] _prefixBuffer;
2020

2121
/**
22-
* Offset within {@link #_prefixBuffer} where there is room
23-
* for prefix.
22+
* Offset within {@link #_prefixBuffer} where there is room for prefix.
2423
*/
2524
protected final int _prefixOffset;
2625

@@ -39,18 +38,12 @@ public class ByteAccumulator
3938

4039
public ByteAccumulator(ByteAccumulator p, int typedTag,
4140
byte[] prefixBuffer, int prefixOffset, int parentStart)
42-
{
43-
this(p, typedTag, prefixBuffer, prefixOffset);
44-
_parentStart = parentStart;
45-
}
46-
47-
public ByteAccumulator(ByteAccumulator p, int typedTag,
48-
byte[] prefixBuffer, int prefixOffset)
4941
{
5042
_parent = p;
5143
_typedTag = typedTag;
5244
_prefixBuffer = prefixBuffer;
5345
_prefixOffset = prefixOffset;
46+
_parentStart = parentStart;
5447
}
5548

5649
public void append(byte[] buf, int offset, int len) {
@@ -66,9 +59,9 @@ public void append(byte[] buf, int offset, int len) {
6659
public ByteAccumulator finish(OutputStream out,
6760
byte[] input, int offset, int len) throws IOException
6861
{
62+
final byte[] prefix = _prefixBuffer;
6963
int start = _prefixOffset;
7064
int ptr;
71-
final byte[] prefix = _prefixBuffer;
7265

7366
if (_typedTag == -1) {
7467
ptr = start;
@@ -77,11 +70,12 @@ public ByteAccumulator finish(OutputStream out,
7770
}
7871

7972
int plen = _segmentBytes + len;
80-
8173
ptr = ProtobufUtil.appendLengthLength(plen, prefix, ptr);
82-
74+
8375
// root? Just output it all
8476
if (_parent == null) {
77+
// 04-Apr-2017, tatu: We know that parent will have flushed anything it might have,
78+
// so `_parentStart` is irrelevant here (but not in the other branch)
8579
out.write(prefix, start, ptr-start);
8680
for (Segment s = _firstSegment; s != null; s = s.next()) {
8781
s.writeTo(out);
@@ -90,6 +84,12 @@ public ByteAccumulator finish(OutputStream out,
9084
out.write(input, offset, len);
9185
}
9286
} else {
87+
// 04-Apr-2017, tatu: for [dataformats-binary#67], need to flush possible
88+
// content parent had...
89+
final int flushLen = _prefixOffset - _parentStart;
90+
if (flushLen > 0) {
91+
_parent.append(input, _parentStart, flushLen);
92+
}
9393
_parent.append(prefix, start, ptr-start);
9494
if (_firstSegment != null) {
9595
_parent.appendAll(_firstSegment, _lastSegment, _segmentBytes);
@@ -101,7 +101,7 @@ public ByteAccumulator finish(OutputStream out,
101101
return _parent;
102102
}
103103

104-
public ByteAccumulator finish(OutputStream out) throws IOException
104+
public ByteAccumulator finish(OutputStream out, byte[] input) throws IOException
105105
{
106106
int start = _prefixOffset;
107107
int ptr;
@@ -117,11 +117,17 @@ public ByteAccumulator finish(OutputStream out) throws IOException
117117

118118
// root? Just output it all
119119
if (_parent == null) {
120+
// 04-Apr-2017, tatu: We know that parent will have flushed anything it might have,
121+
// so `_parentStart` is irrelevant here (but not in the other branch)
120122
out.write(prefix, start, ptr-start);
121123
for (Segment s = _firstSegment; s != null; s = s.next()) {
122124
s.writeTo(out);
123125
}
124126
} else {
127+
final int flushLen = _prefixOffset - _parentStart;
128+
if (flushLen > 0) {
129+
_parent.append(input, _parentStart, flushLen);
130+
}
125131
_parent.append(prefix, start, ptr-start);
126132
if (_firstSegment != null) {
127133
_parent.appendAll(_firstSegment, _lastSegment, _segmentBytes);

protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ProtobufGenerator.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ public final void flush() throws IOException
326326
}
327327
_output.flush();
328328
}
329-
329+
330330
@Override
331331
public void close() throws IOException
332332
{
@@ -1731,42 +1731,43 @@ private final void _startBuffering() throws IOException
17311731
* similar to method above. But somehow that does not seem to be needed...
17321732
* Let's add it just to be safe, still.
17331733
*/
1734+
// 04-Apr-2017, tatu: Most likely this is because this can only happen when we are
1735+
// writing Objects as elements of packed array; and this can not be root-level
1736+
// value: and if so we must be buffering (to get length prefix)
1737+
/*
17341738
if (_buffered == null) {
17351739
int len = ptr - _currStart;
17361740
if (len > 0) {
17371741
ptr = 0;
17381742
_output.write(_currBuffer, _currStart, len);
17391743
}
17401744
}
1745+
*/
17411746
_buffered = new ByteAccumulator(_buffered, -1, _currBuffer, ptr, _currStart);
17421747
ptr += 5;
17431748
_currStart = ptr;
17441749
_currPtr = ptr;
17451750
}
17461751

1752+
/**
1753+
* Helper method called when the current buffering scope is closed;
1754+
* when packed array is completed (`writeEndArray()`) or record is
1755+
* completed (`writeEndObject()`).
1756+
*/
17471757
private final void _finishBuffering() throws IOException
17481758
{
17491759
final int start = _currStart;
1750-
final int newStart = _currPtr;
1760+
final int newStart = _currPtr;
17511761
final int currLen = newStart - start;
17521762

17531763
ByteAccumulator acc = _buffered;
1754-
final ByteAccumulator child = _buffered;
17551764
acc = acc.finish(_output, _currBuffer, start, currLen);
17561765
_buffered = acc;
17571766
if (acc == null) {
17581767
_currStart = 0;
17591768
_currPtr = 0;
17601769
return;
17611770
}
1762-
1763-
// 08-Mar-2017, tatu: for [dataformats-binary#54]
1764-
// need to reposition buffer, otherwise will overwrite
1765-
final int parentStart = child._parentStart;
1766-
final int flushLen = child._prefixOffset - parentStart;
1767-
if (flushLen > 0) {
1768-
_buffered.append(_currBuffer, parentStart, flushLen);
1769-
}
17701771
_currStart = newStart;
17711772
// already same, no need to change
17721773
// _currPtr = newStart;
@@ -1822,7 +1823,7 @@ protected void _complete() throws IOException
18221823
} else {
18231824
acc = acc.finish(_output, _currBuffer, start, currLen);
18241825
while (acc != null) {
1825-
acc = acc.finish(_output);
1826+
acc = acc.finish(_output, _currBuffer);
18261827
}
18271828
_buffered = null;
18281829
}
+1-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
package com.fasterxml.jackson.dataformat.protobuf.failing;
1+
package com.fasterxml.jackson.dataformat.protobuf;
22

33
import com.fasterxml.jackson.annotation.JsonProperty;
44
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
55
import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper;
6-
import com.fasterxml.jackson.dataformat.protobuf.ProtobufTestBase;
76
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchema;
87

98
public class NestedWrite67Test extends ProtobufTestBase

release-notes/VERSION

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Modules:
1616
#54 (protobuf): Some fields are left null
1717
#58 (avro): Regression due to changed namespace of inner enum types
1818
(reported by Peter R)
19-
#62: `java.lang.ArrayIndexOutOfBoundsException` at `CBORGenerator.java`:548
19+
#62: (cbor) `java.lang.ArrayIndexOutOfBoundsException` at `CBORGenerator.java`:548
20+
#67: (proto) Serialization of multiple nesting levels has issues
2021

2122
2.8.7 (21-Feb-2017)
2223

0 commit comments

Comments
 (0)