Skip to content

Commit

Permalink
Merge pull request #323 from kwon37xi/issue_321
Browse files Browse the repository at this point in the history
Fix for #321 EnumNameSerializer
  • Loading branch information
NathanSweet committed Jun 23, 2015
2 parents 820677b + 538bd6c commit 893b814
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
*~
.*.swp
.DS_STORE
*.iml

bin/
target/
.idea/
48 changes: 48 additions & 0 deletions src/com/esotericsoftware/kryo/serializers/EnumNameSerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.esotericsoftware.kryo.serializers;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

/**
* Enum serialize with enum's name.
* <p />
* This serializer prevents reading wrong values when enum's order changed.
*
* @author KwonNam Son <[email protected]>
*/
public class EnumNameSerializer extends Serializer<Enum> {
{
setImmutable(true);
setAcceptsNull(true);
}

private Class<? extends Enum> enumType;

public EnumNameSerializer(Class<? extends Enum> type) {
this.enumType = type;
}

public void write(Kryo kryo, Output output, Enum object) {
if (object == null) {
output.writeString(null);
return;
}
output.writeString(object.name());
}

public Enum read(Kryo kryo, Input input, Class<Enum> type) {
String name = input.readString();
if (name == null) {
return null;
}

try {
return Enum.valueOf(enumType, name);
} catch (IllegalArgumentException e) {
throw new KryoException("Invalid name for enum \"" + type.getName() + "\": " + name, e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.esotericsoftware.kryo.serializers;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoTestCase;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.util.EnumSet;

/**
* @author KwonNam Son <[email protected]>
*/
public class EnumNameSerializerTest extends KryoTestCase {

public void testEnumNameSerializer() {
kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
kryo.register(TestNameEnum.class);
kryo.register(TestAnotherNameEnum.class);

// 1 byte for identifying class name,
// rest bytes for enum's name
roundTrip(6, 6, TestNameEnum.HELLO);
roundTrip(5, 5, TestNameEnum.KRYO);

roundTrip(7, 7, TestAnotherNameEnum.SUNDAY);
roundTrip(8, 8, TestAnotherNameEnum.TUESDAY);

kryo = new Kryo();
kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
kryo.setRegistrationRequired(false);

roundTrip(83, 83, TestNameEnum.WORLD);
roundTrip(91, 91, TestAnotherNameEnum.MONDAY);
}

public void testEnumSetSerializerWithEnumNameSerializer() throws Exception {
kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
kryo.register(EnumSet.class);
kryo.register(TestNameEnum.class);

// roundTrip for EnumSet with EnumNameSerializer does not work.

// test directly
Output output = new Output(1024);
kryo.writeClassAndObject(output, EnumSet.of(TestNameEnum.HELLO, TestNameEnum.WORLD));
byte[] bytes = output.toBytes();

EnumSet<TestNameEnum> enumSet = (EnumSet<TestNameEnum>) kryo.readClassAndObject(new Input(bytes));
assertEquals(enumSet.size(), 2);
assertTrue(enumSet.contains(TestNameEnum.HELLO));
assertTrue(enumSet.contains(TestNameEnum.WORLD));
assertFalse(enumSet.contains(TestNameEnum.KRYO));

// empty EnumSet
roundTrip(3, 6, EnumSet.noneOf(TestNameEnum.class));

}

public void testEnumNameSerializerWithMethods() {
kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);

kryo.register(TestNameEnumWithMethods.class);
roundTrip(6, 6, TestNameEnumWithMethods.ALPHA);
roundTrip(5, 5, TestNameEnumWithMethods.BETA);

kryo = new Kryo();
kryo.addDefaultSerializer(Enum.class, EnumNameSerializer.class);
kryo.setRegistrationRequired(false);

roundTrip(96, 96, TestNameEnumWithMethods.ALPHA);
roundTrip(95, 95, TestNameEnumWithMethods.BETA);

}

public enum TestNameEnum {
HELLO, KRYO, WORLD
}

public enum TestAnotherNameEnum {
SUNDAY, MONDAY, TUESDAY
}

public enum TestNameEnumWithMethods {
ALPHA {
},
BETA {
}
}
}

0 comments on commit 893b814

Please sign in to comment.