Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rpc contracts #10

Merged
merged 1 commit into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ subprojects {

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.2'
testImplementation 'org.assertj:assertj-core:3.22.0'
testImplementation 'org.mockito:mockito-core:3.12.4'
testImplementation 'org.mockito:mockito-inline:3.12.4'
testImplementation 'org.slf4j:slf4j-simple:1.7.32'

testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}
Expand Down
2 changes: 1 addition & 1 deletion common/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dependencies {
implementation 'org.reflections:reflections:0.10.1'
implementation 'org.reflections:reflections:0.10.2'
implementation 'com.squareup:javapoet:1.13.0'
}
6 changes: 3 additions & 3 deletions rpc/rpc-codegen/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ dependencies {
implementation project(':scale:scale-codegen')
implementation project(':transport')

compileOnly 'com.google.auto.service:auto-service-annotations:1.0'
annotationProcessor 'com.google.auto.service:auto-service:1.0'
compileOnly 'com.google.auto.service:auto-service-annotations:1.0.1'
annotationProcessor 'com.google.auto.service:auto-service:1.0.1'

implementation 'com.squareup:javapoet:1.13.0'
testImplementation 'com.google.testing.compile:compile-testing:0.19'
testImplementation 'com.google.code.gson:gson:2.8.8'
testImplementation 'com.google.code.gson:gson:2.8.9'

testCompileOnly project(':rpc:rpc-codegen')
testAnnotationProcessor project(':rpc:rpc-codegen')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.strategyobject.substrateclient.scale.codegen.ScaleAnnotationParser;
import com.strategyobject.substrateclient.scale.codegen.reader.ReaderCompositor;
import com.strategyobject.substrateclient.scale.registries.ScaleReaderRegistry;
import com.strategyobject.substrateclient.transport.RpcObject;
import lombok.NonNull;
import lombok.val;
import lombok.var;
Expand Down Expand Up @@ -83,14 +84,15 @@ private MethodSpec generateDecodeMethod(ProcessorContext context, TypeName class
.addAnnotation(suppressWarnings("unchecked"))
.addModifiers(Modifier.PUBLIC)
.returns(classWildcardTyped)
.addParameter(Object.class, VALUE_ARG)
.addParameter(RpcObject.class, VALUE_ARG)
.addParameter(ArrayTypeName.of(
ParameterizedTypeName.get(
ClassName.get(DecoderPair.class),
WildcardTypeName.subtypeOf(Object.class))),
DECODERS_ARG)
.varargs(true);

shortcutIfNull(methodSpec);
addValidationRules(methodSpec);
addMethodBody(methodSpec, context);

Expand All @@ -100,10 +102,9 @@ private MethodSpec generateDecodeMethod(ProcessorContext context, TypeName class
private void addMethodBody(MethodSpec.Builder methodSpec, ProcessorContext context) throws ProcessingException {
val resultType = JavaPoet.setEachGenericParameterAs(classElement, TypeName.OBJECT);
methodSpec
.addStatement("if ($L == null) { return null; }", VALUE_ARG)
.addStatement("$1T $2L = $1T.getInstance()", RpcDecoderRegistry.class, DECODER_REGISTRY)
.addStatement("$1T $2L = $1T.getInstance()", ScaleReaderRegistry.class, SCALE_READER_REGISTRY)
.addStatement("$1T<$2T, ?> $3L = ($1T<$2T, ?>)$4L", Map.class, String.class, MAP_VAR, VALUE_ARG)
.addStatement("$T<$T, $T> $L = $L.asMap()", Map.class, String.class, RpcObject.class, MAP_VAR, VALUE_ARG)
.addStatement("$1T $2L = new $1T()", resultType, RESULT_VAR)
.beginControlFlow("try");

Expand Down Expand Up @@ -166,13 +167,8 @@ private void setScaleField(MethodSpec.Builder methodSpec,
readerCompositor.traverse(fieldType);
methodSpec
.addStatement(code
.add("$T.$L(",
ScaleUtils.class,
FROM_HEX_STRING)
.add("($T)$L.get($S), ",
String.class,
MAP_VAR,
field)
.add("$T.$L(", ScaleUtils.class, FROM_HEX_STRING)
.add("$L.get($S).asString(), ", MAP_VAR, field)
.add("($T)", ScaleReader.class)
.add(readerCode)
.add("))")
Expand Down Expand Up @@ -225,4 +221,8 @@ private void addValidationRules(MethodSpec.Builder methodSpec) {
}
}
}

private void shortcutIfNull(MethodSpec.Builder methodSpec) {
methodSpec.addStatement("if ($L.isNull()) { return null; }", VALUE_ARG);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private MethodSpec generateEncodeMethod(ProcessorContext context, TypeName class
ENCODERS_ARG)
.varargs(true);

shortcutIfNull(methodSpec);
addValidationRules(methodSpec, context);
addMethodBody(methodSpec, context);

Expand All @@ -100,7 +101,6 @@ private MethodSpec generateEncodeMethod(ProcessorContext context, TypeName class

private void addMethodBody(MethodSpec.Builder methodSpec, ProcessorContext context) throws ProcessingException {
methodSpec
.addStatement("if ($L == null) { return null; }", SOURCE_ARG)
.addStatement("$1T $2L = $1T.getInstance()", RpcEncoderRegistry.class, ENCODER_REGISTRY)
.addStatement("$1T $2L = $1T.getInstance()", ScaleWriterRegistry.class, SCALE_WRITER_REGISTRY)
.addStatement("$1T<$2T, $3T> $4L = new $1T<>()", HashMap.class, String.class, Object.class, RESULT_VAR)
Expand Down Expand Up @@ -223,4 +223,8 @@ private void addValidationRules(MethodSpec.Builder methodSpec, ProcessorContext
}
}
}

private void shortcutIfNull(MethodSpec.Builder methodSpec) {
methodSpec.addStatement("if ($L == null) { return null; }", SOURCE_ARG);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ private CodeBlock getScaleReadCodeBlock(AnnotatedConstruct annotated,
return CodeBlock.builder()
.add("($T) (", resultType)
.add("$T.$L(", ScaleUtils.class, FROM_HEX_STRING)
.add("($T) $L, ($T) ", String.class, arg, ScaleReader.class)
.add("$L.asString(), ($T) ", arg, ScaleReader.class)
.add(readerCode)
.add("))")
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.strategyobject.substrateclient.common.codegen.ProcessingException;
import com.strategyobject.substrateclient.common.codegen.ProcessorContext;
import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription;
import com.strategyobject.substrateclient.transport.RpcObject;
import lombok.NonNull;
import lombok.val;

Expand Down Expand Up @@ -58,7 +59,7 @@ protected void callProviderInterface(MethodSpec.Builder methodSpecBuilder,
.add("$1T<$2T, $3T> $4L = ($5L, $6L) -> { $7N.$8L($5L, ",
BiConsumer.class,
Exception.class,
Object.class,
RpcObject.class,
CALL_BACK_PROXY,
CALL_BACK_EX_ARG,
CALL_BACK_ARG,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
import com.strategyobject.substrateclient.rpc.codegen.substitutes.TestDecodable;
import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.rpc.core.registries.RpcDecoderRegistry;
import com.strategyobject.substrateclient.transport.RpcObject;
import lombok.val;
import org.junit.jupiter.api.Test;

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.HashMap;

import static com.google.testing.compile.CompilationSubject.assertThat;
import static com.google.testing.compile.Compiler.javac;
Expand Down Expand Up @@ -62,23 +60,50 @@ void compilesAndDecodes() { // TODO move this test out of the project
val decoder = registry.resolve(TestDecodable.class)
.inject(DecoderPair.of(registry.resolve(String.class), null));

Object source = gson.fromJson("{\"a\":4,\"b\":\"123\",\"c\":\"some\"," +
"\"d\":[\"1\",\"2\"],\"e\":{\"a\":1,\"b\":2},\"f\":\"0x04000000\"," +
"\"g\":\"0x0c0500000002000000fdffffff\"}",
Object.class);
/*
{
"a": 4,
"b": "123",
"c": "some",
"d": [
"1",
"2"
],
"e": {
"a": null,
"b": 2
},
"f": "0x04000000",
"g": "0x0c0500000002000000fdffffff",
"h": 1.5,
}
*/
val source = RpcObject.of(new HashMap<String, RpcObject>() {{
put("a", RpcObject.of(4));
put("b", RpcObject.of("123"));
put("c", RpcObject.of("some"));
put("d", RpcObject.of(Arrays.asList(RpcObject.of("1"), RpcObject.of("2"))));
put("e", RpcObject.of(new HashMap<String, RpcObject>() {{
put("a", RpcObject.ofNull());
put("b", RpcObject.of(2));
}}));
put("f", RpcObject.of("0x04000000"));
put("g", RpcObject.of("0x0c0500000002000000fdffffff"));
put("h", RpcObject.of(1.5));
}});
val actual = decoder.decode(source);

val expected = new TestDecodable<>(4,
"123",
"some",
Arrays.asList("1", "2"),
Stream.of(
new AbstractMap.SimpleEntry<>("a", 1),
new AbstractMap.SimpleEntry<>("b", 2))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)),
new HashMap<String, Float>() {{
put("a", null);
put("b", 2f);
}},
4,
Arrays.asList(5, 2, -3));

val actual = decoder.decode(source);

Arrays.asList(5, 2, -3),
1.5f);
assertEquals(gson.toJson(expected), gson.toJson(actual));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.strategyobject.substrateclient.rpc.codegen.substitutes.TestSection;
import com.strategyobject.substrateclient.transport.ProviderInterface;
import com.strategyobject.substrateclient.transport.RpcBoolean;
import com.strategyobject.substrateclient.transport.RpcObject;
import lombok.val;
import org.junit.jupiter.api.Test;

Expand All @@ -19,7 +21,7 @@ public class RpcSectionFactoryTest {
@Test
void createsRpcSectionAndCallsMethod() throws ExecutionException, InterruptedException, RpcInterfaceInitializationException {
val expected = true;
val sendFuture = CompletableFuture.completedFuture((Object) Boolean.valueOf(expected));
val sendFuture = CompletableFuture.completedFuture((RpcObject) new RpcBoolean(expected));
val provider = mock(ProviderInterface.class);
when(provider.send(anyString(), anyList()))
.thenReturn(sendFuture);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ public class TestDecodable<T> {
private String b;
private T c;
private List<String> d;
private Map<String, Integer> e;
private Map<String, Float> e;
@Scale
private int f;
@Scale
private List<Integer> g;
private float h;
}
3 changes: 2 additions & 1 deletion rpc/rpc-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dependencies {
implementation project(':common')
implementation project(':scale')
implementation project(':transport')

testImplementation 'com.google.code.gson:gson:2.8.8'
testImplementation 'com.google.code.gson:gson:2.8.9'
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.strategyobject.substrateclient.rpc.core;

import com.strategyobject.substrateclient.transport.RpcObject;

public interface RpcDecoder<T> {
T decode(Object value, DecoderPair<?>... decoders);
T decode(RpcObject value, DecoderPair<?>... decoders);

default RpcDecoder<T> inject(DecoderPair<?>... dependencies) {
return (jsonToken, decoders) -> this.decode(jsonToken, dependencies);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
import com.google.common.base.Preconditions;
import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.rpc.core.RpcDecoder;
import com.strategyobject.substrateclient.transport.RpcObject;

public abstract class AbstractDecoder<T> implements RpcDecoder<T> {
@Override
public final T decode(Object value, DecoderPair<?>... decoders) {
if (value == null) {
public final T decode(RpcObject value, DecoderPair<?>... decoders) {
if (value.isNull()) {
return null;
}

// TODO I am not sure should it be the first instruction of the method or not
checkArguments(value, decoders);

return decodeNonNull(value, decoders);
}

protected abstract T decodeNonNull(Object value, DecoderPair<?>[] decoders);
protected abstract T decodeNonNull(RpcObject value, DecoderPair<?>[] decoders);

protected void checkArguments(Object value, DecoderPair<?>[] decoders) {
protected void checkArguments(RpcObject value, DecoderPair<?>[] decoders) {
Preconditions.checkArgument(decoders == null || decoders.length == 0);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.strategyobject.substrateclient.rpc.core.decoders;

import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.transport.RpcObject;

public class BooleanDecoder extends AbstractDecoder<Boolean> {
@Override
protected Boolean decodeNonNull(Object value, DecoderPair<?>[] decoders) {
return (Boolean) value;
protected Boolean decodeNonNull(RpcObject value, DecoderPair<?>[] decoders) {
return value.asBoolean();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.strategyobject.substrateclient.rpc.core.decoders;

import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.transport.RpcObject;

public class ByteDecoder extends AbstractDecoder<Byte> {
@Override
protected Byte decodeNonNull(Object value, DecoderPair<?>[] decoders) {
return ((Double) value).byteValue();
protected Byte decodeNonNull(RpcObject value, DecoderPair<?>[] decoders) {
return value.asNumber().byteValue();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.strategyobject.substrateclient.rpc.core.decoders;

import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.transport.RpcObject;

public class DoubleDecoder extends AbstractDecoder<Double> {
@Override
protected Double decodeNonNull(Object value, DecoderPair<?>[] decoders) {
return (Double) value;
protected Double decodeNonNull(RpcObject value, DecoderPair<?>[] decoders) {
return value.asNumber().doubleValue();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.strategyobject.substrateclient.rpc.core.decoders;

import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.transport.RpcObject;

public class FloatDecoder extends AbstractDecoder<Float> {
@Override
protected Float decodeNonNull(Object value, DecoderPair<?>[] decoders) {
return ((Double) value).floatValue();
protected Float decodeNonNull(RpcObject value, DecoderPair<?>[] decoders) {
return value.asNumber().floatValue();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.strategyobject.substrateclient.rpc.core.decoders;

import com.strategyobject.substrateclient.rpc.core.DecoderPair;
import com.strategyobject.substrateclient.transport.RpcObject;

public class IntDecoder extends AbstractDecoder<Integer> {
@Override
protected Integer decodeNonNull(Object value, DecoderPair<?>[] decoders) {
return ((Double) value).intValue();
protected Integer decodeNonNull(RpcObject value, DecoderPair<?>[] decoders) {
return value.asNumber().intValue();
}
}
Loading