diff --git a/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java b/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java index 4a1cda0..c5b0304 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java +++ b/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java @@ -7,6 +7,9 @@ import java.io.*; import java.util.*; public class Generator { + + private static final String VARIABLE_SUFFIX = "$"; + public static void generateJava( final List types, final List functions, final File abstractsFile, final File typesFile, final File functionsFile) throws IOException { @@ -68,16 +71,13 @@ public class Generator { writer.write(extendsName); writer.write(" {\n"); - int n = 0; - for (TLArg arg : object.args) { - if (arg.flags) { + for (int i = 0; i < object.args.size(); ++i) { + if (object.args.get(i).flags) { continue; } - writer.write("private "); - writer.write(arg.javaType()); - writer.write(" var" + n); - ++n; + writer.write(object.args.get(i).javaType()); + writer.write(" " + VARIABLE_SUFFIX + i); writer.write(";\n"); } @@ -89,7 +89,7 @@ public class Generator { // Objects will be created with nothing set and the arguments set with .argument(value). // TODO - writer.write("public void serialize(final BinaryWriter writer) {}\n"); + writeSerialize(writer, object); writer.write("public void deserialize(final BinaryReader reader) {}\n"); writer.write("}\n"); @@ -101,6 +101,49 @@ public class Generator { writer.write("}\n"); } + private static void writeSerialize(final Writer writer, final TLObject object) throws IOException { + writer.write("public void serialize(final BinaryWriter writer) {\n"); + for (final TLArg arg : object.args) { + if (arg.flags) { + writer.write("int "); + writer.write(arg.name); + writer.write(" = 0;\n"); + } + } + for (int i = 0; i < object.args.size(); ++i) { + final TLArg arg = object.args.get(i); + if (arg.flag != null) { + writer.write("if (" + VARIABLE_SUFFIX + i); + writer.write(arg.javaSetCheck()); + writer.write(") { "); + writer.write(arg.flag.flagName); + writer.write(" |= " + (1 << arg.flag.flagIndex)); + writer.write("; }\n"); + } + } + for (int i = 0; i < object.args.size(); ++i) { + final TLArg arg = object.args.get(i); + if (arg.flag != null) { + writer.write("if (" + VARIABLE_SUFFIX + i); + writer.write(arg.javaSetCheck()); + writer.write(") { "); + } + if (!arg.flags) { + writer.write("writer.write(" + VARIABLE_SUFFIX + i + ");"); + } else { + writer.write("writer.write("); + writer.write(arg.name); + writer.write(");"); + } + if (arg.flag != null) { + writer.write(" }\n"); + } else { + writer.write('\n'); + } + } + writer.write("}\n"); + } + private static Map> byNamespace(final Iterable objects) { final Map> result = new HashMap<>(); for (final TLObject object : objects) { diff --git a/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java b/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java index a21e9dd..32d5061 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java +++ b/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java @@ -61,7 +61,7 @@ public class TLArg { } break; case "long": - // TODO handle int128 and int256 properly + // TODO handle int128 and int256 properly case "int128": case "int256": if (flag == null && !nested) { @@ -110,6 +110,10 @@ public class TLArg { return builder.toString(); } + public String javaSetCheck() { + return types.size() == 1 && types.get(0).equals("true") ? "" : " != null"; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -134,9 +138,9 @@ public class TLArg { return builder.toString(); } - private static final class Flag { - private final String flagName; - private final int flagIndex; + public static final class Flag { + public final String flagName; + public final int flagIndex; private Flag(final String flagName, final int flagIndex) { this.flagName = flagName; diff --git a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java index d59b8db..3e9f8f7 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java +++ b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java @@ -1,5 +1,91 @@ package io.github.lonamiwebs.overgram.utils; +import io.github.lonamiwebs.overgram.tl.TLObject; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.List; + public class BinaryWriter { + private final ByteBuffer buffer; + + public BinaryWriter() { + buffer = ByteBuffer.allocate(128); + buffer.order(ByteOrder.LITTLE_ENDIAN); + } + + public void write(final int value) { + buffer.putInt(value); + } + + public void write(final long value) { + buffer.putLong(value); + } + + public void write(final double value) { + buffer.putDouble(value); + } + + public void write(final boolean value) { + buffer.putInt(value ? 0x997275b5 : 0xbc799737); + } + + public void write(final byte[] bytes) { + int padding; + if (bytes.length < 254) { + padding = (bytes.length + 1) % 4; + buffer.put((byte) bytes.length); + buffer.put(bytes); + } else { + padding = bytes.length % 4; + buffer.putInt(bytes.length << 8 | 0xfe); + buffer.put(bytes); + } + if (padding != 0) { + for (padding = 4 - padding; padding-- != 0; ) { + buffer.put((byte) 0); + } + } + } + + public void write(final String string) { + buffer.put(StandardCharsets.UTF_8.encode(string)); + } + + // TODO Handle boxed vs unboxed types (and vector<>) + public void write(final TLObject object) { + object.serialize(this); + } + + @SuppressWarnings("unchecked") + public void write(final List objects) { + write(0x1cb5c415); + write(objects.size()); + if (objects.isEmpty()) { + return; + } + + final Object first = objects.get(0); + if (first instanceof TLObject) { + for (final TLObject obj : (List) objects) { + write(obj); + } + } else if (first instanceof Integer) { + for (final Integer obj : (List) objects) { + write(obj); + } + } else if (first instanceof Long) { + for (final Long obj : (List) objects) { + write(obj); + } + } else if (first instanceof byte[]) { + for (final byte[] obj : (List) objects) { + write(obj); + } + } else { + throw new UnsupportedOperationException(); + } + } }