Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,7 @@ public JsonGenerator writeString(char[] text, int offset, int clen) throws Jacks
}
if (_currField.wireType != WireType.LENGTH_PREFIXED) {
_writeEnum(new String(text, offset, clen));
return this;
}

// Could guarantee with 42 chars or less; but let's do bit more speculative
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package tools.jackson.dataformat.protobuf;

import java.io.ByteArrayOutputStream;

import org.junit.jupiter.api.Test;

import tools.jackson.core.JsonGenerator;

import tools.jackson.dataformat.protobuf.schema.ProtobufSchema;
import tools.jackson.dataformat.protobuf.schema.ProtobufSchemaLoader;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* Tests for writing enum-valued fields through the {@code char[]} variant of
* {@code writeString()}, which used to fall through and additionally emit the
* value as a length-prefixed String.
*/
public class WriteEnumAsCharArrayTest extends ProtobufTestBase
{
private final ProtobufMapper MAPPER = newObjectMapper();

@Test
public void testEnumViaCharArrayMatchesString() throws Exception
{
ProtobufSchema schema = ProtobufSchemaLoader.std.parse(PROTOC_SEARCH_REQUEST);

byte[] viaString = _write(schema, false);
byte[] viaCharArray = _write(schema, true);

// 1 byte for tag, 1 byte for enum index -- nothing more
assertEquals(2, viaString.length);
assertArrayEquals(viaString, viaCharArray);
}

@Test
public void testEnumViaCharArrayRoundTrips() throws Exception
{
ProtobufSchema schema = ProtobufSchemaLoader.std.parse(PROTOC_SEARCH_REQUEST);
SearchRequest result = MAPPER.readerFor(SearchRequest.class).with(schema)
.readValue(_write(schema, true));
assertEquals(Corpus.WEB, result.corpus);
}

private byte[] _write(ProtobufSchema schema, boolean useCharArray) throws Exception
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (JsonGenerator g = MAPPER.writer(schema).createGenerator(bytes)) {
g.writeStartObject();
g.writeName("corpus");
if (useCharArray) {
char[] ch = "WEB".toCharArray();
g.writeString(ch, 0, ch.length);
} else {
g.writeString("WEB");
}
g.writeEndObject();
}
return bytes.toByteArray();
}
}
3 changes: 3 additions & 0 deletions release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ PJ Fanning (@pjfanning)
* Contributed #763: (protobuf) Use `VarHandle` for multi-byte primitive reads
and writes in `ProtobufParser` / `ProtobufGenerator`
(3.3.0)
* Contributed #772: (protobuf) `ProtobufGenerator.writeString(char[],int,int)`
writes enum values twice
(3.3.0)
3 changes: 3 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ implementations)
#767: (smile) Use more efficient `String` construction wrt "Compact Strings"
for "short" ASCII text values of async parser
(fix by @cowtowncoder, w/ Claude code)
#772: (protobuf) `ProtobufGenerator.writeString(char[],int,int)` writes enum
values twice
(contributed by @pjfanning)

3.2.3 (not yet released)

Expand Down
Loading