Generate code to read TLRequests' result

master
Lonami Exo 2018-07-24 21:16:35 +02:00
parent 5f018c709e
commit 7fa0d033d6
6 changed files with 147 additions and 85 deletions

View File

@ -19,10 +19,10 @@ public class Generator {
writeAbstract(writer, types);
}
try (final Writer writer = new BufferedWriter(new FileWriter(typesFile))) {
writeCode(writer, "Types", null, types, true);
writeCode(writer, "Types", "%s", types, false);
}
try (final Writer writer = new BufferedWriter(new FileWriter(functionsFile))) {
writeCode(writer, "Functions", "TLRequest", functions, false);
writeCode(writer, "Functions", "TLRequest<%s>", functions, true);
}
}
@ -50,7 +50,7 @@ public class Generator {
private static void writeCode(
final Writer writer, final String className, final String extendsName,
final List<TLObject> objects, final boolean generateGetList) throws IOException {
final List<TLObject> objects, final boolean functions) throws IOException {
writer.write("package io.github.lonamiwebs.overgram.tl;\n");
writer.write("import io.github.lonamiwebs.overgram.utils.BinaryReader;\n");
writer.write("import io.github.lonamiwebs.overgram.utils.BinaryWriter;\n");
@ -60,6 +60,7 @@ public class Generator {
writer.write("public class ");
writer.write(className);
writer.write(" {\n");
final boolean nested = extendsName.contains("<");
for (final Map.Entry<String, List<TLObject>> nsObjects : byNamespace(objects).entrySet()) {
if (!nsObjects.getKey().isEmpty()) {
writer.write("public static class ");
@ -70,12 +71,8 @@ public class Generator {
writer.write("public static class ");
writer.write(Utils.toCamelCase(object.name, true));
writer.write(" extends ");
if (extendsName == null) {
writer.write("Abstract.");
writer.write(Utils.toCamelCase(object.type, true));
} else {
writer.write(extendsName);
}
writer.write(String.format(extendsName, object.typeAsArg().javaType(nested)));
writer.write(" {\n");
writer.write("public static final int CONSTRUCTOR_ID = " + object.code + ";\n");
@ -120,6 +117,9 @@ public class Generator {
writeSerialize(writer, object);
writeDeserialize(writer, object);
if (functions) {
writeReadResult(writer, object);
}
writer.write("}\n");
}
@ -128,7 +128,7 @@ public class Generator {
}
}
if (generateGetList) {
if (!functions) {
writer.write("public static TLObject getFromId(final int id) throws ClassNotFoundException {\n");
writer.write("switch (id) {\n");
@ -221,66 +221,7 @@ public class Generator {
// TODO We don't handle boxed vs. unboxed here, either
writer.write(VARIABLE_SUFFIX + i);
writer.write(" = ");
if (arg.types.get(0).equalsIgnoreCase("vector")) {
switch (arg.types.get(1)) {
case "int":
writer.write("reader.readIntList();");
break;
case "long":
writer.write("reader.readLongList();");
break;
case "string":
writer.write("reader.readStringList();");
break;
case "bytes":
writer.write("reader.readBytesList();");
break;
case "int128":
case "int256":
case "double":
case "Bool":
case "true":
throw new UnsupportedOperationException("vector of " + arg.types.get(1));
default:
writer.write("(");
writer.write(arg.javaType());
writer.write(") reader.readTlList();");
break;
}
} else {
switch (arg.types.get(0)) {
case "int":
writer.write("reader.readInt();");
break;
case "long":
writer.write("reader.readLong();");
break;
case "int128":
writer.write("reader.readInt128();");
break;
case "int256":
writer.write("reader.readInt256();");
break;
case "double":
writer.write("reader.readDouble();");
break;
case "Bool":
case "true":
writer.write("reader.readBoolean();");
break;
case "string":
writer.write("reader.readString();");
break;
case "bytes":
writer.write("reader.readBytes();");
break;
default:
writer.write("(");
writer.write(arg.javaType());
writer.write(") reader.readTl();");
break;
}
}
writeRead(writer, arg);
if (arg.flag != null) {
writer.write(" }\n");
@ -291,6 +232,79 @@ public class Generator {
writer.write("}\n");
}
private static void writeRead(final Writer writer, final TLArg arg) throws IOException {
if (arg.types.get(0).equalsIgnoreCase("vector")) {
switch (arg.types.get(1)) {
case "int":
writer.write("reader.readIntList();");
break;
case "long":
writer.write("reader.readLongList();");
break;
case "string":
writer.write("reader.readStringList();");
break;
case "bytes":
writer.write("reader.readBytesList();");
break;
case "int128":
case "int256":
case "double":
case "Bool":
case "true":
throw new UnsupportedOperationException("vector of " + arg.types.get(1));
default:
writer.write("(");
writer.write(arg.javaType());
writer.write(") reader.readTlList();");
break;
}
} else {
switch (arg.types.get(0)) {
case "int":
writer.write("reader.readInt();");
break;
case "long":
writer.write("reader.readLong();");
break;
case "int128":
writer.write("reader.readInt128();");
break;
case "int256":
writer.write("reader.readInt256();");
break;
case "double":
writer.write("reader.readDouble();");
break;
case "Bool":
case "true":
writer.write("reader.readBoolean();");
break;
case "string":
writer.write("reader.readString();");
break;
case "bytes":
writer.write("reader.readBytes();");
break;
default:
writer.write("(");
writer.write(arg.javaType());
writer.write(") reader.readTl();");
break;
}
}
}
private static void writeReadResult(final Writer writer, final TLObject object) throws IOException {
writer.write("public ");
writer.write(object.typeAsArg().javaType(true));
writer.write(" readResult(final BinaryReader reader) throws ClassNotFoundException {\n");
writer.write("return ");
writeRead(writer, object.typeAsArg());
writer.write('\n');
writer.write("}\n");
}
private static Map<String, List<TLObject>> byNamespace(final Iterable<TLObject> objects) {
final Map<String, List<TLObject>> result = new HashMap<>();
for (final TLObject object : objects) {

View File

@ -4,6 +4,7 @@ import io.github.lonamiwebs.overgram.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TLArg {
public final String name;
@ -11,17 +12,19 @@ public class TLArg {
public final boolean flags;
public final Flag flag;
public final boolean genericDefinition;
public final TLArg genericOn;
private TLArg(final String name, final List<String> types, final boolean flags, final Flag flag,
final boolean genericDefinition) {
final boolean genericDefinition, final TLArg genericOn) {
this.name = name;
this.types = types;
this.flags = flags;
this.flag = flag;
this.genericDefinition = genericDefinition;
this.genericOn = genericOn;
}
public static TLArg fromString(String string) {
public static TLArg fromString(final String string, final Map<String, TLArg> genericDefinitions) {
final String[] tmp = string.split(":");
boolean genericDefinition = false;
@ -52,13 +55,38 @@ public class TLArg {
}
types.add(tmp[1]);
return new TLArg(tmp[0], types, flags, flag, genericDefinition);
final TLArg genericOn;
if (!genericDefinition && types.size() == 1) {
genericOn = genericDefinitions.get(types.get(0));
} else {
genericOn = null;
}
return new TLArg(tmp[0], types, flags, flag, genericDefinition, genericOn);
}
public static TLArg fromUnnamedString(final String string, final Map<String, TLArg> genericDefinitions) {
return fromString(":" + string, genericDefinitions);
}
public String javaType() {
final StringBuilder builder = new StringBuilder();
return javaType(false);
}
boolean nested = false;
public String javaType(boolean nested) {
if (genericOn != null) {
return genericOn.javaType();
}
if (genericDefinition) {
if (types.size() == 1 && types.get(0).equals("Type")) {
return "TLObject";
} else {
throw new UnsupportedOperationException();
}
}
final StringBuilder builder = new StringBuilder();
for (final String type : types) {
if (type.startsWith("!")) {
if (nested) {

View File

@ -1,7 +1,9 @@
package io.github.lonamiwebs.overgram.parser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TLObject {
@ -11,12 +13,15 @@ public class TLObject {
public final int code;
public final List<TLArg> args;
public final String type;
private final Map<String, TLArg> genericDefinitions;
private TLObject(final String fullname, final int code, final List<TLArg> args, final String type) {
private TLObject(final String fullname, final int code, final List<TLArg> args, final String type,
final Map<String, TLArg> genericDefinitions) {
this.fullname = fullname;
this.code = code;
this.args = args;
this.type = type;
this.genericDefinitions = genericDefinitions;
final String[] nsName = fullname.split("\\.");
if (nsName.length == 1) {
@ -47,13 +52,23 @@ public class TLObject {
code = tmp.length == 1 ? "0" : tmp[1];
final List<TLArg> args = new ArrayList<>();
final Map<String, TLArg> genericDefinitions = new HashMap<>(1);
if (!string.isEmpty()) {
for (final String part : string.split(" ")) {
args.add(TLArg.fromString(part));
final TLArg arg = TLArg.fromString(part, genericDefinitions);
if (arg.genericDefinition) {
genericDefinitions.put(arg.name, arg);
}
args.add(arg);
}
}
return new TLObject(name, Integer.parseUnsignedInt(code, 16), args, type);
return new TLObject(name, Integer.parseUnsignedInt(code, 16), args, type, genericDefinitions);
}
public TLArg typeAsArg() {
return TLArg.fromUnnamedString(type, genericDefinitions);
}
@Override

View File

@ -80,7 +80,7 @@ ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;
destroy_session#e7512126 session_id:long = DestroySessionRes;
http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
//http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
//test.useGzipPacked = GzipPacked;
//test.useServerDhInnerData = Server_DH_inner_data;

View File

@ -5,14 +5,15 @@ import io.github.lonamiwebs.overgram.network.connection.Connection;
import io.github.lonamiwebs.overgram.tl.*;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
import javax.naming.OperationNotSupportedException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class MTProtoSender {
private final MTProtoState state;
@ -261,7 +262,11 @@ public class MTProtoSender {
// TODO RPC error
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result()));
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
try {
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
} catch (ClassNotFoundException e) {
replyMessage.future.completeExceptionally(e);
}
}
public void handleContainer(final TLMessage message) throws InterruptedException {

View File

@ -2,6 +2,6 @@ package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
public abstract class TLRequest<T extends TLObject> extends TLObject {
public abstract T readResult(final BinaryReader reader);
public abstract class TLRequest<T> extends TLObject {
public abstract T readResult(final BinaryReader reader) throws ClassNotFoundException;
}