Skip to content

Commit c6c1f97

Browse files
committed
Fixed #54 (manual merge of patch)
1 parent 8321c68 commit c6c1f97

File tree

4 files changed

+175
-13
lines changed

4 files changed

+175
-13
lines changed

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,25 @@ public class ByteAccumulator
3030

3131
protected int _segmentBytes;
3232

33+
/**
34+
* Used to cache start pointer for nested message's parent
35+
*
36+
* @since 2.8.8
37+
*/
38+
protected int _parentStart;
39+
3340
public ByteAccumulator(ByteAccumulator p, int typedTag,
34-
byte[] prefixBuffer, int prefixOffset)
41+
byte[] prefixBuffer, int prefixOffset, int parentStart)
3542
{
36-
_parent = p;
37-
_typedTag = typedTag;
38-
_prefixBuffer = prefixBuffer;
39-
_prefixOffset = prefixOffset;
43+
this(p, typedTag, prefixBuffer, prefixOffset);
44+
_parentStart = parentStart;
4045
}
4146

42-
public ByteAccumulator(ByteAccumulator p,
43-
byte[] prefixBuffer, int prefixOffset) {
47+
public ByteAccumulator(ByteAccumulator p, int typedTag,
48+
byte[] prefixBuffer, int prefixOffset)
49+
{
4450
_parent = p;
45-
_typedTag = -1;
51+
_typedTag = typedTag;
4652
_prefixBuffer = prefixBuffer;
4753
_prefixOffset = prefixOffset;
4854
}

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

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,8 +1709,8 @@ private final void _startBuffering(int typedTag) throws IOException
17091709
_output.write(_currBuffer, start, len);
17101710
}
17111711
}
1712+
_buffered = new ByteAccumulator(_buffered, typedTag, _currBuffer, ptr, _currStart);
17121713
_currStart = _currPtr = ptr + 10;
1713-
_buffered = new ByteAccumulator(_buffered, typedTag, _currBuffer, ptr);
17141714
}
17151715

17161716
/**
@@ -1734,24 +1734,28 @@ private final void _startBuffering() throws IOException
17341734
_output.write(_currBuffer, _currStart, len);
17351735
}
17361736
}
1737-
1737+
_buffered = new ByteAccumulator(_buffered, -1, _currBuffer, ptr, _currStart);
17381738
_currStart = _currPtr = ptr + 5;
1739-
_buffered = new ByteAccumulator(_buffered, _currBuffer, ptr);
17401739
}
17411740

17421741
private final void _finishBuffering() throws IOException
17431742
{
17441743
final int start = _currStart;
1745-
final int currLen = _currPtr - start;
1744+
final int newStart = _currPtr;
1745+
final int currLen = newStart - start;
17461746

17471747
ByteAccumulator acc = _buffered;
1748+
final ByteAccumulator child = _buffered;
17481749
acc = acc.finish(_output, _currBuffer, start, currLen);
17491750
_buffered = acc;
17501751
if (acc == null) {
17511752
_currStart = 0;
17521753
_currPtr = 0;
17531754
} else {
1754-
_currStart = _currPtr;
1755+
// 08-Mar-2017, tatu: for [dataformats-binary#54]
1756+
// need to reposition buffer, otherwise will overwrite
1757+
final int parentStart = child._parentStart;
1758+
_flushBuffer(parentStart, child._prefixOffset - parentStart, newStart);
17551759
}
17561760
}
17571761

@@ -1788,6 +1792,32 @@ protected final void _ensureMore() throws IOException
17881792
_currBuffer = ProtobufUtil.allocSecondary(_currBuffer);
17891793
}
17901794

1795+
/**
1796+
* Flushes current buffer either to output or (if buffered) ByteAccumulator (append)
1797+
* and sets current start position to current pointer.
1798+
*
1799+
* @since 2.8.8
1800+
*/
1801+
protected final void _flushBuffer(final int start, final int currLen, final int newStart) throws IOException
1802+
{
1803+
ByteAccumulator acc = _buffered;
1804+
if (acc == null) {
1805+
// without accumulation, we know buffer is free for reuse
1806+
if (currLen > 0) {
1807+
_output.write(_currBuffer, start, currLen);
1808+
}
1809+
_currStart = 0;
1810+
_currPtr = 0;
1811+
return;
1812+
}
1813+
// but with buffered, need to append, allocate new buffer (since old
1814+
// almost certainly contains buffered data)
1815+
if (currLen > 0) {
1816+
acc.append(_currBuffer, start, currLen);
1817+
}
1818+
_currPtr = _currStart = newStart;
1819+
}
1820+
17911821
protected void _complete() throws IOException
17921822
{
17931823
_complete = true;
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package com.fasterxml.jackson.dataformat.protobuf;
2+
3+
import java.io.IOException;
4+
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper;
9+
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchema;
10+
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchemaLoader;
11+
12+
public class RoundtripNestedMessageTest extends ProtobufTestBase
13+
{
14+
private static final String VALUE_A = "value";
15+
private static final String VALUE_B = "value-b";
16+
private static final String VALUE_C = "valc";
17+
private static final String VALUE_SUB_A = "a-value!";
18+
19+
private static final String PROTO = //
20+
"message TestObject {\n" + //
21+
"optional string a = 1;\n" + //
22+
"optional TestSub b = 2;\n" + //
23+
"}\n" + //
24+
"message TestSub {;\n" + //
25+
"optional string c = 2;\n" + //
26+
"optional string b = 3;\n" + //
27+
"optional TestSubSub d = 4;\n" + //
28+
"}\n" + //
29+
"message TestSubSub {;\n" + //
30+
"optional string a = 1;\n" + //
31+
"}\n"; //
32+
33+
static class TestObject {
34+
String a;
35+
TestSub b;
36+
37+
public String getA() {
38+
return a;
39+
}
40+
41+
public void setA(String a) {
42+
this.a = a;
43+
}
44+
45+
public TestSub getB() {
46+
return b;
47+
}
48+
49+
public void setB(TestSub b) {
50+
this.b = b;
51+
}
52+
}
53+
54+
// ordering would be needed prior to fix for [#59]
55+
//@com.fasterxml.jackson.annotation.JsonPropertyOrder({"d", "b", "c"})
56+
static class TestSub {
57+
String b;
58+
String c;
59+
TestSubSub d;
60+
61+
public String getB() {
62+
return b;
63+
}
64+
65+
public void setB(String b) {
66+
this.b = b;
67+
}
68+
69+
public String getC() {
70+
return c;
71+
}
72+
73+
public void setC(String c) {
74+
this.c = c;
75+
}
76+
77+
public TestSubSub getD() {
78+
return d;
79+
}
80+
81+
public void setD(TestSubSub d) {
82+
this.d = d;
83+
}
84+
}
85+
86+
public static class TestSubSub {
87+
String a;
88+
89+
public String getA() {
90+
return a;
91+
}
92+
93+
public void setA(String a) {
94+
this.a = a;
95+
}
96+
}
97+
98+
@Test
99+
public void testNestedRoundtrip() throws IOException
100+
{
101+
TestObject testClass = new TestObject();
102+
ProtobufMapper om = new ProtobufMapper();
103+
ProtobufSchema s = ProtobufSchemaLoader.std.parse(PROTO);
104+
testClass.a = VALUE_A;
105+
testClass.b = new TestSub();
106+
testClass.b.b = VALUE_B;
107+
testClass.b.c = VALUE_C;
108+
// if this following row is commented out, test succeeds with old code
109+
testClass.b.d = new TestSubSub();
110+
testClass.b.d.a = VALUE_SUB_A;
111+
112+
byte[] proto = om.writer(s)
113+
.writeValueAsBytes(testClass);
114+
TestObject res = om.readerFor(TestObject.class).with(s)
115+
.readValue(proto);
116+
117+
Assert.assertEquals(VALUE_A, res.a);
118+
Assert.assertEquals(VALUE_C, res.b.c);
119+
Assert.assertEquals(VALUE_B, res.b.b);
120+
Assert.assertEquals(VALUE_SUB_A, res.b.d.a);
121+
}
122+
}

release-notes/VERSION

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Modules:
1111

1212
2.9.0 (not yet released)
1313

14+
2.8.8 (not yet released)
15+
16+
#54 (protobuf): Some fields are left null
17+
1418
2.8.7 (21-Feb-2017)
1519

1620
#34 (avro): Reading Avro with specified reader and writer schemas

0 commit comments

Comments
 (0)