Skip to content

Commit

Permalink
Add serdes support for arrays and maps; Add generic type retrieval fo…
Browse files Browse the repository at this point in the history
…r enums
  • Loading branch information
rchomczyk committed Feb 28, 2024
1 parent 9b9f5ae commit b783965
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 14 deletions.
9 changes: 9 additions & 0 deletions cory-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,13 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>com.pivovarit</groupId>
<artifactId>throwing-function</artifactId>
<version>1.5.1</version>
<scope>compile</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;

public interface PacketPacker extends Closeable {

PacketPacker packArrayHeader(int value) throws IOException;

<V> PacketPacker packArray(V[] value) throws IOException;

PacketPacker packBinaryHeader(int value) throws IOException;

PacketPacker packPayload(byte[] value) throws IOException;
Expand All @@ -49,6 +52,8 @@ public interface PacketPacker extends Closeable {

PacketPacker packDouble(Double value) throws IOException;

<K, V> PacketPacker packMap(Map<K, V> value) throws IOException;

PacketPacker packMapHeader(int value) throws IOException;

PacketPacker packInstant(Instant value) throws IOException;
Expand All @@ -57,6 +62,8 @@ public interface PacketPacker extends Closeable {

PacketPacker packEnum(Enum<?> value) throws IOException;

<T> PacketPacker packAuto(T value) throws IOException;

PacketPacker packNil() throws IOException;

PacketPacker flush() throws IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;

public interface PacketUnpacker extends Closeable {
Expand All @@ -29,6 +30,8 @@ public interface PacketUnpacker extends Closeable {

int unpackArrayHeader() throws IOException;

<V> V[] unpackArray() throws IOException;

int unpackBinaryHeader() throws IOException;

byte[] unpackPayload() throws IOException;
Expand All @@ -53,11 +56,15 @@ public interface PacketUnpacker extends Closeable {

int unpackMapHeader() throws IOException;

<K, V> Map<K, V> unpackMap() throws IOException;

Instant unpackInstant() throws IOException;

Duration unpackDuration() throws IOException;

<T extends Enum<T>> T unpackEnum(Class<T> expectedType) throws IOException;
<T extends Enum<T>> T unpackEnum() throws IOException;

<T> T unpackAuto() throws IOException;

boolean hasNext() throws IOException;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2023 cory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package moe.rafal.cory.serdes;

public class PacketUnpackingException extends IllegalStateException {

PacketUnpackingException(String message) {
super(message);
}
}
12 changes: 6 additions & 6 deletions cory-serdes-msgpack/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
</properties>

<dependencies>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.9.8</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.pivovarit</groupId>
<artifactId>throwing-function</artifactId>
<version>1.5.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.9.8</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>moe.rafal</groupId>
<artifactId>cory-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@

package moe.rafal.cory.serdes;

import static moe.rafal.cory.serdes.MessagePackPacketPackerUtils.PACKET_PACKER_BY_BOXED_TYPE;
import static moe.rafal.cory.serdes.MessagePackPacketPackerUtils.getBoxedType;

import com.pivovarit.function.ThrowingBiConsumer;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePacker;
Expand All @@ -39,6 +43,16 @@ public PacketPacker packArrayHeader(int value) throws IOException {
return this;
}

@Override
public <V> PacketPacker packArray(final V[] value) throws IOException {
return packOrNil(value, (packer, val) -> {
packer.packArrayHeader(val.length);
for (final V currentValue : value) {
this.packAuto(currentValue);
}
});
}

@Override
public PacketPacker packBinaryHeader(int value) throws IOException {
underlyingPacker.packBinaryHeader(value);
Expand Down Expand Up @@ -105,6 +119,17 @@ public PacketPacker packMapHeader(int value) throws IOException {
return this;
}

@Override
public <K, V> PacketPacker packMap(final Map<K, V> value) throws IOException {
return packOrNil(value, (packer, val) -> {
packer.packMapHeader(val.size());
for (final Map.Entry<K, V> entry : value.entrySet()) {
this.packAuto(entry.getKey());
this.packAuto(entry.getValue());
}
});
}

@Override
public PacketPacker packInstant(Instant value) throws IOException {
return packOrNil(value, (packer, val) -> packer.packString(val.toString()));
Expand All @@ -117,7 +142,27 @@ public PacketPacker packDuration(Duration value) throws IOException {

@Override
public PacketPacker packEnum(Enum<?> value) throws IOException {
return packOrNil(value, (packer, val) -> packer.packString(val.name()));
return packOrNil(value, (packer, val) -> {
packer.packString(val.getDeclaringClass().getName());
packer.packString(val.name());
});
}

@Override
public @SuppressWarnings("unchecked") <T> PacketPacker packAuto(final T value) throws IOException {
return packOrNil(value, (packer, val) -> {
final Class<?> rawType = val.getClass();
final Class<?> type = getBoxedType(val.getClass());
if (!rawType.isEnum()) {
this.packString(type.getName());
}

final ThrowingBiConsumer<PacketPacker, T, IOException> packerFunction =
(ThrowingBiConsumer<PacketPacker, T, IOException>) PACKET_PACKER_BY_BOXED_TYPE.get(
type
);
packerFunction.accept(this, val);
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2023 cory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package moe.rafal.cory.serdes;

import static java.lang.String.format;

import com.pivovarit.function.ThrowingBiConsumer;
import com.pivovarit.function.ThrowingFunction;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

final class MessagePackPacketPackerUtils {

static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED_TYPE;
static final Map<
Class<?>, ThrowingBiConsumer<PacketPacker, ?, IOException>> PACKET_PACKER_BY_BOXED_TYPE;
static final Map<
Class<?>, ThrowingFunction<PacketUnpacker, ?, IOException>> PACKET_UNPACKER_BY_BOXED_TYPE;

static {
PRIMITIVE_TO_BOXED_TYPE = new HashMap<>();
PRIMITIVE_TO_BOXED_TYPE.put(boolean.class, Boolean.class);
PRIMITIVE_TO_BOXED_TYPE.put(int.class, Integer.class);
PRIMITIVE_TO_BOXED_TYPE.put(byte.class, Byte.class);
PRIMITIVE_TO_BOXED_TYPE.put(long.class, Long.class);
PRIMITIVE_TO_BOXED_TYPE.put(short.class, Short.class);
PRIMITIVE_TO_BOXED_TYPE.put(float.class, Float.class);
PRIMITIVE_TO_BOXED_TYPE.put(double.class, Double.class);
PACKET_PACKER_BY_BOXED_TYPE = new HashMap<>();
PACKET_PACKER_BY_BOXED_TYPE.put(String.class, (packer, value) -> packer.packString((String) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Boolean.class, (packer, value) -> packer.packBoolean((Boolean) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Integer.class, (packer, value) -> packer.packInt((Integer) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Byte.class, (packer, value) -> packer.packByte((Byte) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Long.class, (packer, value) -> packer.packLong((Long) value));
PACKET_PACKER_BY_BOXED_TYPE.put(UUID.class, (packer, value) -> packer.packUUID((UUID) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Short.class, (packer, value) -> packer.packShort((Short) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Float.class, (packer, value) -> packer.packFloat((Float) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Double.class, (packer, value) -> packer.packDouble((Double) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Instant.class, (packer, value) -> packer.packInstant((Instant) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Duration.class, (packer, value) -> packer.packDuration((Duration) value));
PACKET_PACKER_BY_BOXED_TYPE.put(Enum.class, (packer, value) -> packer.packEnum((Enum<?>) value));
PACKET_UNPACKER_BY_BOXED_TYPE = new HashMap<>();
PACKET_UNPACKER_BY_BOXED_TYPE.put(String.class, PacketUnpacker::unpackString);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Boolean.class, PacketUnpacker::unpackBoolean);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Integer.class, PacketUnpacker::unpackInt);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Byte.class, PacketUnpacker::unpackByte);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Long.class, PacketUnpacker::unpackLong);
PACKET_UNPACKER_BY_BOXED_TYPE.put(UUID.class, PacketUnpacker::unpackUUID);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Short.class, PacketUnpacker::unpackShort);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Float.class, PacketUnpacker::unpackFloat);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Double.class, PacketUnpacker::unpackDouble);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Instant.class, PacketUnpacker::unpackInstant);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Duration.class, PacketUnpacker::unpackDuration);
PACKET_UNPACKER_BY_BOXED_TYPE.put(Enum.class, PacketUnpacker::unpackEnum);
}

private MessagePackPacketPackerUtils() {

}

static Class<?> getClassByNameOrThrow(final String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException exception) {
throw new PacketUnpackingException(format(
"Could not find class by name %s",
className
));
}
}

static Class<?> getBoxedType(final Class<?> type) {
if (type.isPrimitive()) {
return PRIMITIVE_TO_BOXED_TYPE.get(type);
}

if (type.isEnum()) {
return Enum.class;
}

return type;
}
}
Loading

0 comments on commit b783965

Please sign in to comment.