Skip to content

Commit 219d597

Browse files
committed
Fix issue FasterXML#54
1 parent 22c1d34 commit 219d597

File tree

3 files changed

+148
-11
lines changed

3 files changed

+148
-11
lines changed

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,22 @@ public class ByteAccumulator
2929
protected Segment _firstSegment, _lastSegment;
3030

3131
protected int _segmentBytes;
32+
33+
// used to cache start pointer for nested message's parent
34+
protected int _parentStart = 0;
3235

3336
public ByteAccumulator(ByteAccumulator p, int typedTag,
34-
byte[] prefixBuffer, int prefixOffset)
37+
byte[] prefixBuffer, int prefixOffset, int parentStart)
3538
{
36-
_parent = p;
37-
_typedTag = typedTag;
38-
_prefixBuffer = prefixBuffer;
39-
_prefixOffset = prefixOffset;
39+
this(p, typedTag, prefixBuffer, prefixOffset);
40+
this._parentStart = parentStart;
4041
}
4142

42-
public ByteAccumulator(ByteAccumulator p,
43-
byte[] prefixBuffer, int prefixOffset) {
43+
public ByteAccumulator(ByteAccumulator p, int typedTag,
44+
byte[] prefixBuffer, int prefixOffset)
45+
{
4446
_parent = p;
45-
_typedTag = -1;
47+
_typedTag = typedTag;
4648
_prefixBuffer = prefixBuffer;
4749
_prefixOffset = prefixOffset;
4850
}

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

Lines changed: 7 additions & 3 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
/**
@@ -1735,8 +1735,8 @@ private final void _startBuffering() throws IOException
17351735
}
17361736
}
17371737

1738+
_buffered = new ByteAccumulator(_buffered, -1, _currBuffer, ptr, _currStart);
17381739
_currStart = _currPtr = ptr + 5;
1739-
_buffered = new ByteAccumulator(_buffered, _currBuffer, ptr);
17401740
}
17411741

17421742
private final void _finishBuffering() throws IOException
@@ -1745,13 +1745,17 @@ private final void _finishBuffering() throws IOException
17451745
final int currLen = _currPtr - 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+
_currStart = child._parentStart;
1756+
_currPtr = child._prefixOffset;
1757+
// need to reallocate buffer, otherwise will overwrite
1758+
_ensureMore();
17551759
}
17561760
}
17571761

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.fasterxml.jackson.dataformat.protobuf;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.ByteArrayOutputStream;
5+
import java.io.IOException;
6+
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
10+
import com.fasterxml.jackson.databind.ObjectReader;
11+
import com.fasterxml.jackson.databind.ObjectWriter;
12+
import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper;
13+
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchema;
14+
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchemaLoader;
15+
16+
public class NestedMessages {
17+
18+
private static final String PROTO = //
19+
"message TestObject {\n" + //
20+
"optional string a = 1;\n" + //
21+
"optional TestSub b = 2;\n" + //
22+
"}\n" + //
23+
"message TestSub {;\n" + //
24+
"optional string c = 2;\n" + //
25+
"optional string b = 3;\n" + //
26+
"optional TestSubSub d = 4;\n" + //
27+
"}\n" + //
28+
"message TestSubSub {;\n" + //
29+
"optional string a = 1;\n" + //
30+
"}\n"; //
31+
32+
public static class TestObject {
33+
String a;
34+
TestSub b;
35+
36+
public String getA() {
37+
return a;
38+
}
39+
40+
public void setA(String a) {
41+
this.a = a;
42+
}
43+
44+
public TestSub getB() {
45+
return b;
46+
}
47+
48+
public void setB(TestSub b) {
49+
this.b = b;
50+
}
51+
52+
// The following annotation to force "d" as first field is needed before
53+
// the fix
54+
// @JsonPropertyOrder(value={"d", "b", "c"})
55+
public static class TestSub {
56+
String b;
57+
String c;
58+
TestSubSub d;
59+
60+
public String getB() {
61+
return b;
62+
}
63+
64+
public void setB(String b) {
65+
this.b = b;
66+
}
67+
68+
public String getC() {
69+
return c;
70+
}
71+
72+
public void setC(String c) {
73+
this.c = c;
74+
}
75+
76+
public TestSubSub getD() {
77+
return d;
78+
}
79+
80+
public void setD(TestSubSub d) {
81+
this.d = d;
82+
}
83+
84+
public static class TestSubSub {
85+
String a;
86+
87+
public String getA() {
88+
return a;
89+
}
90+
91+
public void setA(String a) {
92+
this.a = a;
93+
}
94+
}
95+
}
96+
}
97+
98+
@Test
99+
public void testProto() throws IOException {
100+
101+
TestObject testClass = new TestObject();
102+
ProtobufMapper om = new ProtobufMapper();
103+
ProtobufSchema s = ProtobufSchemaLoader.std.load(new ByteArrayInputStream(PROTO.getBytes()));
104+
ObjectReader r = om.readerFor(TestObject.class).with(s);
105+
ObjectWriter w = om.writer(s);
106+
ByteArrayOutputStream out = new ByteArrayOutputStream() {
107+
@Override
108+
public synchronized void write(byte[] b, int off, int len) {
109+
super.write(b, off, len);
110+
System.out.println("Off " + off + " len " + len);
111+
}
112+
};
113+
testClass.a = "value";
114+
testClass.b = new TestObject.TestSub();
115+
testClass.b.b = "value-b";
116+
testClass.b.c = "valc";
117+
// if this following row is commented out, test succeeds with old code
118+
testClass.b.d = new TestObject.TestSub.TestSubSub();
119+
testClass.b.d.a = "a-value!";
120+
121+
w.writeValue(out, testClass);
122+
System.out.println("Size: " + out.size());
123+
124+
TestObject res = r.readValue(out.toByteArray());
125+
126+
Assert.assertEquals("value", res.a);
127+
Assert.assertEquals("valc", res.b.c);
128+
Assert.assertEquals("value-b", res.b.b);
129+
}
130+
131+
}

0 commit comments

Comments
 (0)