From 2f22e74eca0915c284a68017df1ddd2ad69bd43e Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Mon, 23 Jul 2018 19:28:23 +0200 Subject: [PATCH] Write deserialization code --- .../overgram/generator/Generator.java | 93 +++++++++++++++- .../lonamiwebs/overgram/tl/TLObject.java | 1 + .../overgram/utils/BinaryReader.java | 103 ++++++++++++++++++ .../overgram/utils/BinaryWriter.java | 2 +- 4 files changed, 196 insertions(+), 3 deletions(-) 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 c4aa8c8..4e8d49a 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java +++ b/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java @@ -54,7 +54,7 @@ public class Generator { writer.write("import io.github.lonamiwebs.overgram.utils.BinaryReader;\n"); writer.write("import io.github.lonamiwebs.overgram.utils.BinaryWriter;\n"); writer.write("import java.util.List;\n"); - writer.write("@SuppressWarnings(\"unused\")\n"); + writer.write("@SuppressWarnings(\"ALL\")\n"); writer.write("public class "); writer.write(className); writer.write(" {\n"); @@ -95,7 +95,7 @@ public class Generator { // TODO writeSerialize(writer, object); - writer.write("public void deserialize(final BinaryReader reader) {}\n"); + writeDeserialize(writer, object); writer.write("}\n"); } @@ -149,6 +149,95 @@ public class Generator { writer.write("}\n"); } + private static void writeDeserialize(final Writer writer, final TLObject object) throws IOException { + writer.write("public void deserialize(final BinaryReader reader) {\n"); + for (int i = 0; i < object.args.size(); ++i) { + final TLArg arg = object.args.get(i); + if (arg.flags) { + writer.write("int "); + writer.write(arg.name); + writer.write(" = reader.readInt();\n"); + continue; + } + + if (arg.flag != null) { + writer.write("if (("); + writer.write(arg.flag.flagName); + writer.write(" & " + (1 << arg.flag.flagIndex)); + writer.write(") != 0) { "); + } + + // TODO The only nested type we handle is Vector<>, avoid that + // 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": + // TODO handle int128 and int256 properly + case "int128": + case "int256": + writer.write("reader.readLong();"); + 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; + } + } + + 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/tl/TLObject.java b/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java index 0843655..f7eaa30 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java +++ b/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java @@ -5,5 +5,6 @@ import io.github.lonamiwebs.overgram.utils.BinaryWriter; public abstract class TLObject { public abstract void serialize(final BinaryWriter writer); + public abstract void deserialize(final BinaryReader reader); } diff --git a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java index 3e761a0..9c9a895 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java +++ b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java @@ -1,4 +1,107 @@ package io.github.lonamiwebs.overgram.utils; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + public class BinaryReader { + private final ByteBuffer buffer; + + public BinaryReader(final ByteBuffer buffer) { + this.buffer = buffer; + } + + public int readInt() { + return buffer.getInt(); + } + + public List readIntList() { + buffer.position(buffer.position() + 4); // vector code + final int size = buffer.getInt(); + final List result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(buffer.getInt()); + } + return result; + } + + public long readLong() { + return buffer.getLong(); + } + + public List readLongList() { + buffer.position(buffer.position() + 4); // vector code + final int size = buffer.getInt(); + final List result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(buffer.getLong()); + } + return result; + } + + public double readDouble() { + return buffer.getDouble(); + } + + public boolean readBoolean() { + return buffer.getInt() == 0x997275b5; + } + + public byte[] readBytes() { + int length; + int padding; + final byte first = buffer.get(); + if (first == (byte) 0xfe) { + buffer.position(buffer.position() - 1); + length = buffer.getInt() >> 8; + padding = length % 4; + } else { + length = first; + padding = (length + 1) % 4; + } + + final byte[] data = new byte[length]; + buffer.get(data); + buffer.position(buffer.position() + padding); + return data; + } + + public List readBytesList() { + buffer.position(buffer.position() + 4); // vector code + final int size = buffer.getInt(); + final List result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(readBytes()); + } + return result; + } + + public String readString() { + return StandardCharsets.UTF_8.decode(ByteBuffer.wrap(readBytes())).toString(); + } + + public List readStringList() { + buffer.position(buffer.position() + 4); // vector code + final int size = buffer.getInt(); + final List result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(readString()); + } + return result; + } + + public Object readTl() { + return null; + } + + public List readTlList() { + buffer.position(buffer.position() + 4); // vector code + final int size = buffer.getInt(); + final List result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(readTl()); + } + return result; + } } 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 3e9f8f7..3f542be 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java +++ b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java @@ -34,7 +34,7 @@ public class BinaryWriter { public void write(final byte[] bytes) { int padding; - if (bytes.length < 254) { + if (bytes.length < 0xfe) { padding = (bytes.length + 1) % 4; buffer.put((byte) bytes.length); buffer.put(bytes);