CoralState is a lightweight, garbage-free and fast Java library for collecting objects and data structures into an in-memory state, serializing the complete state to a ByteBuffer, and restoring it later from disk, memory, or the network.
It uses CoralDS for fast garbage-free data-structures, CoralProto for fast garbage-free serialization and CoralPool for fast garbage-free object pooling.
- Simple key-based API for adding, getting, checking and removing values.
- Fast binary serialization of the complete State to and from a
ByteBufferwithout creating any garbage. - Support for all Java primitives without boxing.
- Support for
Stringand top-levelCharSequenceandByteBuffervalues. - Support for all CoralDS data structures (maps, lists and sets).
- Support for recursively nested data structures, such as lists of maps and maps of lists.
- Support for application objects through CoralProto codecs.
- Validation of unsupported values before they are added or serialized.
- Reusable State instances.
- Support for easy schema evolution through CoralProto.
- Designed for single-threaded applications. Non-thread-safe by design.
Define a mutable object class, for example Person.
public final class Person {
public static final int MAX_NAME = 64;
private final StringBuilder name = new StringBuilder(MAX_NAME);
private int age;
public Person() {
// must be defined so CoralState can create pooled instances
}
public Person(CharSequence name, int age) {
setName(name);
setAge(age);
}
public CharSequence getName() {
return name;
}
public void setName(CharSequence name) {
this.name.setLength(0);
this.name.append(name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Person other)) return false;
return age == other.age && CharSequence.compare(name, other.name) == 0;
}
@Override
public int hashCode() {
int hash = 0;
for (int i = 0; i < name.length(); i++) {
hash = 31 * hash + name.charAt(i);
}
return 31 * hash + age;
}
}Define its CoralProto codec:
public final class PersonCodec implements StateCodec<Person, PersonCodec.PersonProto> {
private final PersonProto personProto = new PersonProto();
@Override
public Class<Person> javaType() {
return Person.class;
}
@Override
public PersonProto getProto() {
return personProto;
}
@Override
public void encode(Person person, PersonProto personProto) {
personProto.name.set(person.getName());
personProto.age.set(person.getAge());
}
@Override
public void decode(PersonProto personProto, Person person) {
person.setName(personProto.name.get());
person.setAge(personProto.age.get());
}
public static final class PersonProto extends AbstractProto {
public static final char TYPE = 'P';
public static final char SUBTYPE = 'R';
public final TypeField type = new TypeField(this, TYPE);
public final SubtypeField subtype = new SubtypeField(this, SUBTYPE);
public final VarCharsField name = new VarCharsField(this, Person.MAX_NAME);
public final IntField age = new IntField(this);
}
}Register the Person codec:
StateRegistry registry = new StateRegistry();
registry.register(new PersonCodec());Create a State containing one Person and a CoralDS list of three people:
State original = new State(registry);
original.put("person", new Person("Alice", 31));
ArrayList<Person> people = new ArrayList<>();
people.add(new Person("Bob", 42));
people.add(new Person("Carol", 27));
people.add(new Person("Dave", 35));
original.put("people", people);Write and restore the complete State:
ByteBuffer buffer = ByteBuffer.allocate(original.getSerializedLength());
original.writeTo(buffer);
buffer.flip();
State restored = new State(registry);
restored.readFrom(buffer);
Assert.assertEquals(original, restored);
Person person = (Person) restored.get("person");
ArrayList<Person> restoredPeople = (ArrayList<Person>) restored.get("people");The same State can be retained across reads:
State reusable = new State(registry);
reusable.readFrom(buffer);
reusable.clear();
reusable.readFrom(nextBuffer);CoralState support for schema evolution is naturally inherited from CoralProto. For example, fields can be appended to PersonProto while preserving compatibility with older State data.