Skip to content

Commit

Permalink
Lost enum constants during transit serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
apangin committed Nov 27, 2022
1 parent dbe4ca5 commit 48c1843
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 13 deletions.
30 changes: 17 additions & 13 deletions src/one/nio/serial/EnumSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,51 +28,55 @@ public class EnumSerializer extends Serializer<Enum> {
static final AtomicInteger enumCountMismatches = new AtomicInteger();
static final AtomicInteger enumMissedConstants = new AtomicInteger();

private String[] names;
private Enum[] values;

EnumSerializer(Class cls) {
super(cls);
this.values = cls().getEnumConstants();
this.names = new String[values.length];
for (int i = 0; i < names.length; i++) {
names[i] = values[i].name();
}
}

@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
Enum[] ownValues = cls().getEnumConstants();
out.writeShort(ownValues.length);
for (Enum v : ownValues) {
out.writeUTF(v.name());
out.writeShort(names.length);
for (String name : names) {
out.writeUTF(name);
}
}

@Override
@SuppressWarnings("unchecked")
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
String[] constants = new String[in.readUnsignedShort()];
for (int i = 0; i < constants.length; i++) {
constants[i] = in.readUTF();
this.names = new String[in.readUnsignedShort()];
for (int i = 0; i < names.length; i++) {
names[i] = in.readUTF();
}

try {
super.readExternal(in);
} catch (ClassNotFoundException e) {
if ((Repository.getOptions() & Repository.ENUM_STUBS) == 0) throw e;
this.cls = StubGenerator.generateEnum(uniqueName("Enum"), constants);
this.cls = StubGenerator.generateEnum(uniqueName("Enum"), names);
this.origin = Origin.GENERATED;
}

Enum[] ownValues = cls().getEnumConstants();
if (ownValues.length != constants.length) {
if (ownValues.length != names.length) {
Repository.log.warn("[" + Long.toHexString(uid) + "] Enum count mismatch for " + descriptor + ": " +
ownValues.length + " local vs. " + constants.length + " stream constants");
ownValues.length + " local vs. " + names.length + " stream constants");
enumCountMismatches.incrementAndGet();
}

// 1. Find exact matches
EnumSet usedConstants = EnumSet.noneOf(cls);
this.values = new Enum[constants.length];
for (int i = 0; i < constants.length; i++) {
values[i] = findMatch(constants[i], usedConstants);
this.values = new Enum[names.length];
for (int i = 0; i < names.length; i++) {
values[i] = findMatch(names[i], usedConstants);
}

// 2. Handle renaming
Expand Down
22 changes: 22 additions & 0 deletions test/one/nio/serial/SerializationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import one.nio.serial.sample.Sample;
import one.nio.util.Base64;
import one.nio.util.Utf8;
import org.junit.Test;

import java.io.IOException;
Expand Down Expand Up @@ -242,6 +243,27 @@ public void testEnum() throws IOException, ClassNotFoundException {
checkSerialize(new EnumSerializer(ComplexEnum.class));
}

private enum MagicEnum {
MAGIC1, MAGIC2, MAGIC3
}

@Test
public void testEnumDoubleConvert() throws IOException, ClassNotFoundException {
Serializer<MagicEnum> enumSerializer = Repository.get(MagicEnum.class);
byte[] bytes = Serializer.serialize(enumSerializer);

Repository.removeSerializer(enumSerializer.uid);

// Exchange the order of MAGIC1 and MAGIC3 in the serialized form
int m1 = Utf8.indexOf(MagicEnum.MAGIC1.name().getBytes(), bytes);
int m3 = Utf8.indexOf(MagicEnum.MAGIC3.name().getBytes(), bytes);
bytes[m1 + 5] = '3';
bytes[m3 + 5] = '1';

byte[] copy = Serializer.serialize(Serializer.deserialize(bytes));
assertArrayEquals(bytes, copy);
}

@Test
public void testUrls() throws IOException, ClassNotFoundException, URISyntaxException {
checkSerialize(new URI("socket://192.168.0.1:2222/?param1=value1&param2=value2"));
Expand Down

0 comments on commit 48c1843

Please sign in to comment.