diff --git a/pom.xml b/pom.xml index 6079d103f..db79d1774 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 network.casper casper-java-sdk - 0.3.5 + 0.3.6 Casper Java SDK Casper Java SDK https://casperlabs.io/ diff --git a/src/main/java/com/casper/sdk/service/serialization/cltypes/CLValueBuilder.java b/src/main/java/com/casper/sdk/service/serialization/cltypes/CLValueBuilder.java index a5c44b960..9d1a7be74 100644 --- a/src/main/java/com/casper/sdk/service/serialization/cltypes/CLValueBuilder.java +++ b/src/main/java/com/casper/sdk/service/serialization/cltypes/CLValueBuilder.java @@ -89,7 +89,10 @@ public static CLMap map(final Map map) { throw new ValueNotFoundException("Maps must contain at least one key pair"); } - return new CLMap(TYPES_FACTORY.getInstance(CLType.MAP).serialize(map), + final byte[] bytes = TYPES_FACTORY.getInstance(CLType.MAP).serialize(map); + + return new CLMap( + bytes, new CLMapTypeInfo( map.keySet().iterator().next().getCLTypeInfo(), map.values().iterator().next().getCLTypeInfo() diff --git a/src/main/java/com/casper/sdk/service/serialization/cltypes/MapSerializer.java b/src/main/java/com/casper/sdk/service/serialization/cltypes/MapSerializer.java index 0be2c95ef..ade82313f 100644 --- a/src/main/java/com/casper/sdk/service/serialization/cltypes/MapSerializer.java +++ b/src/main/java/com/casper/sdk/service/serialization/cltypes/MapSerializer.java @@ -23,24 +23,38 @@ public MapSerializer(final TypesFactory typesFactory) { public byte[] serialize(final Object toSerialize) { if (toSerialize instanceof CLMap) { - if (((CLMap) toSerialize).isModified() || ((CLMap) toSerialize).getBytes() == null) { + // The map is mutable to the bytes need to be reserialized if modified or not yet created + if (isModifiedOrNotYetSerialized((CLMap) toSerialize)) { ((CLMap) toSerialize).setModified(false); - return ByteUtils.concat( - typesFactory.getInstance(CLType.U32).serialize(((CLMap) toSerialize).size()), - buildMapBytes((CLMap)toSerialize) - ); + //noinspection unchecked + return serializeMap((Map) toSerialize); } else { - // The map has not been modified so write as is + // The map is not new and has not been modified so write as is return ((CLMap) toSerialize).getBytes(); } + } else if (toSerialize instanceof Map) { + //noinspection unchecked + return serializeMap((Map) toSerialize); } else { return new byte[0]; } } - private byte[] buildMapBytes(final CLMap clMap) { + private boolean isModifiedOrNotYetSerialized(final CLMap toSerialize) { + return toSerialize.isModified() || toSerialize.getBytes() == null; + } + + private byte[] serializeMap(final Map toSerialize) { + return ByteUtils.concat( + typesFactory.getInstance(CLType.U32).serialize(toSerialize.size()), + buildKeyValueBytes(toSerialize) + ); + } + + private byte[] buildKeyValueBytes(final Map clMap) { + final ByteArrayBuilder builder = new ByteArrayBuilder(); for (Map.Entry entry : clMap.entrySet()) { diff --git a/src/main/java/com/casper/sdk/service/serialization/types/AbstractByteSerializer.java b/src/main/java/com/casper/sdk/service/serialization/types/AbstractByteSerializer.java index 04a33a7d1..96ba033f9 100644 --- a/src/main/java/com/casper/sdk/service/serialization/types/AbstractByteSerializer.java +++ b/src/main/java/com/casper/sdk/service/serialization/types/AbstractByteSerializer.java @@ -3,10 +3,7 @@ import com.casper.sdk.service.serialization.cltypes.TypesFactory; import com.casper.sdk.service.serialization.cltypes.TypesSerializer; import com.casper.sdk.service.serialization.util.ByteArrayBuilder; -import com.casper.sdk.types.CLByteArrayInfo; -import com.casper.sdk.types.CLOptionTypeInfo; -import com.casper.sdk.types.CLType; -import com.casper.sdk.types.CLTypeInfo; +import com.casper.sdk.types.*; abstract class AbstractByteSerializer implements ByteSerializer { @@ -40,11 +37,22 @@ byte[] toBytesForCLTypeInfo(final CLTypeInfo typeInfo) { case OPTION: return getOptionType(typeInfo); + case MAP: + return getMapType((CLMapTypeInfo) typeInfo); + default: throw new IllegalArgumentException("Wrong type " + typeInfo.getType()); } } + private byte[] getMapType(final CLMapTypeInfo typeInfo) { + return new ByteArrayBuilder() + .append(getTypeBytes(typeInfo)) + .append(getTypeBytes(typeInfo.getKeyType())) + .append(getTypeBytes(typeInfo.getValueType())) + .toByteArray(); + } + public TypesSerializer getU32Serializer() { return u32Serializer; } diff --git a/src/test/java/com/casper/sdk/service/serialization/types/CLValueByteSerializerTest.java b/src/test/java/com/casper/sdk/service/serialization/types/CLValueByteSerializerTest.java index 9c34f3b42..512bca93e 100644 --- a/src/test/java/com/casper/sdk/service/serialization/types/CLValueByteSerializerTest.java +++ b/src/test/java/com/casper/sdk/service/serialization/types/CLValueByteSerializerTest.java @@ -2,12 +2,10 @@ import com.casper.sdk.service.serialization.cltypes.CLValueBuilder; import com.casper.sdk.service.serialization.cltypes.TypesFactory; +import com.casper.sdk.service.serialization.util.CollectionUtils; import com.casper.sdk.types.*; import org.junit.jupiter.api.Test; -import java.util.LinkedHashMap; -import java.util.Map; - import static com.casper.sdk.service.serialization.util.ByteUtils.concat; import static com.casper.sdk.service.serialization.util.ByteUtils.decodeHex; import static org.hamcrest.MatcherAssert.assertThat; @@ -40,7 +38,6 @@ void u64toBytes() { @Test void u512ValueToBytes() { - final CLValue source = new CLValue( decodeHex("0500e40b5402"), CLType.U512, @@ -95,7 +92,6 @@ void byteOptionArrayKeyValue() { assertThat(byteSerializer.toBytes(optionValue), is(expected)); } - @Test void keyValueToBytes() { @@ -118,4 +114,23 @@ void keyValueToBytes() { assertThat(byteSerializer.toBytes(clKeyValue), is(expected)); } + + + @Test + void clMapTypeBytesTest() { + + final CLValue key = CLValueBuilder.string("ABC"); + final CLValue value = CLValueBuilder.i32(10); + final byte[] expectedBytes = {1, 0, 0, 0, 3, 0, 0, 0, 65, 66, 67, 10, 0, 0, 0}; + + // Assert the value builder can generate the bytes + final CLMap clMap = CLValueBuilder.map(CollectionUtils.Map.of(key, value)); + assertThat(clMap.getBytes(), is(expectedBytes)); + + final byte[] expectedWithTypeBytes = {15, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 65, 66, 67, 10, 0, 0, 0, 17, 10, 1}; + + // Obtain the value with its type info + final byte[] bytes = byteSerializer.toBytes(clMap); + assertThat(bytes, is(expectedWithTypeBytes)); + } }