enterprise ready tdapi
This commit is contained in:
parent
a9b4b6f44a
commit
c834615846
249
__main__.py
249
__main__.py
@ -7,6 +7,72 @@ from code_writer import CodeWriter
|
|||||||
|
|
||||||
natives = ["int", "long", "boolean", "String", "double", "byte[]", "byte"]
|
natives = ["int", "long", "boolean", "String", "double", "byte[]", "byte"]
|
||||||
|
|
||||||
|
native_to_object = {
|
||||||
|
"boolean": "Boolean",
|
||||||
|
"byte[]": "Byte",
|
||||||
|
"byte": "Byte",
|
||||||
|
"int": "Integer",
|
||||||
|
"short": "Short",
|
||||||
|
"char": "Character",
|
||||||
|
"long": "Long",
|
||||||
|
"float": "Float",
|
||||||
|
"double": "Double",
|
||||||
|
"String": "String"
|
||||||
|
}
|
||||||
|
|
||||||
|
comment = ("/**", "* ", "*/")
|
||||||
|
|
||||||
|
cmp_natives = natives.copy()
|
||||||
|
cmp_natives.remove("String")
|
||||||
|
cmp_natives.remove("byte[]")
|
||||||
|
|
||||||
|
|
||||||
|
def split_docs(docs: typing.List[str]) -> typing.List[str]:
|
||||||
|
tokens = " ".join(docs).split(" ")
|
||||||
|
result = [tokens[0]]
|
||||||
|
|
||||||
|
for token in tokens[1:]:
|
||||||
|
if len(" ".join(result[-1]) + token) < 70:
|
||||||
|
result[-1] += f" {token}"
|
||||||
|
else:
|
||||||
|
result.append(token)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def extract_doc(lines: typing.List[str], line: int) -> typing.List[str]:
|
||||||
|
line = next(
|
||||||
|
n
|
||||||
|
for n in range(line - 2, 0, -1)
|
||||||
|
if lines[n].startswith("/**")
|
||||||
|
)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
|
||||||
|
while True:
|
||||||
|
line += 1
|
||||||
|
|
||||||
|
if lines[line].startswith("*/"):
|
||||||
|
break
|
||||||
|
|
||||||
|
current = lines[line].split(" ", maxsplit=1)[-1]
|
||||||
|
|
||||||
|
if current.strip() != "*":
|
||||||
|
result.append(current)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def hash_object(name: str, typ: str) -> str:
|
||||||
|
if not typ.endswith("[]"):
|
||||||
|
return f"{name} == null ? 0 : {name}.hashCode()"
|
||||||
|
|
||||||
|
elif typ.endswith("[][]"):
|
||||||
|
return f"Arrays.deepHashCode({name})"
|
||||||
|
|
||||||
|
else:
|
||||||
|
return f"Arrays.hashCode({name})"
|
||||||
|
|
||||||
|
|
||||||
def deserialize_tdapi(output: CodeWriter, arg_name: str, arg_type: str, cont, classes, null_check: bool = True):
|
def deserialize_tdapi(output: CodeWriter, arg_name: str, arg_type: str, cont, classes, null_check: bool = True):
|
||||||
if null_check:
|
if null_check:
|
||||||
@ -241,6 +307,7 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
inside_function_class: bool = False
|
inside_function_class: bool = False
|
||||||
inside_object_container_class: bool = False
|
inside_object_container_class: bool = False
|
||||||
container_class_name: typing.Optional[str] = None
|
container_class_name: typing.Optional[str] = None
|
||||||
|
current_class_docs: typing.Optional[typing.List[str]] = None
|
||||||
function_depth: int = 0
|
function_depth: int = 0
|
||||||
|
|
||||||
function_classes = OrderedDict()
|
function_classes = OrderedDict()
|
||||||
@ -252,11 +319,12 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
container_classes: typing.List[str] = []
|
container_classes: typing.List[str] = []
|
||||||
# [class_name, ...]
|
# [class_name, ...]
|
||||||
|
|
||||||
current_arguments: typing.Optional[typing.List[typing.Tuple[str, str]]] = None
|
current_arguments: typing.Optional[typing.List[typing.Tuple[str, str, typing.List[str]]]] = None
|
||||||
# [(arg_name, arg_type), ...]
|
# [(arg_name, arg_type), ...]
|
||||||
|
|
||||||
for line in data_input.readlines():
|
lines = list(map(str.strip, data_input.readlines()))
|
||||||
line = line.strip()
|
|
||||||
|
for no, line in enumerate(lines):
|
||||||
keywords = line.split()
|
keywords = line.split()
|
||||||
|
|
||||||
if not keywords:
|
if not keywords:
|
||||||
@ -285,7 +353,8 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
|
|
||||||
if inside_object_class and keywords[-1] == "}":
|
if inside_object_class and keywords[-1] == "}":
|
||||||
inside_object_class = False
|
inside_object_class = False
|
||||||
object_classes[current_class_name] = (current_constructor, container_class_name, current_arguments)
|
object_classes[current_class_name] = (current_constructor, container_class_name,
|
||||||
|
current_arguments, current_class_docs)
|
||||||
container_class_name = None
|
container_class_name = None
|
||||||
current_arguments = None
|
current_arguments = None
|
||||||
current_class_name = None
|
current_class_name = None
|
||||||
@ -294,7 +363,8 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
|
|
||||||
if inside_function_class and keywords[0] == "}":
|
if inside_function_class and keywords[0] == "}":
|
||||||
inside_function_class = False
|
inside_function_class = False
|
||||||
function_classes[current_class_name] = (current_constructor, container_class_name, current_arguments)
|
function_classes[current_class_name] = (current_constructor, container_class_name,
|
||||||
|
current_arguments, current_class_docs)
|
||||||
current_arguments = None
|
current_arguments = None
|
||||||
container_class_name = None
|
container_class_name = None
|
||||||
current_class_name = None
|
current_class_name = None
|
||||||
@ -303,7 +373,7 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
|
|
||||||
if inside_function_class or inside_object_class:
|
if inside_function_class or inside_object_class:
|
||||||
if len(keywords) == 3 and keywords[-1].endswith(";"):
|
if len(keywords) == 3 and keywords[-1].endswith(";"):
|
||||||
current_arguments.append((keywords[1], keywords[2][:-1]))
|
current_arguments.append((keywords[1], keywords[2][:-1], extract_doc(lines, no)))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if len(keywords) == 7 and keywords[4] == "CONSTRUCTOR":
|
if len(keywords) == 7 and keywords[4] == "CONSTRUCTOR":
|
||||||
@ -330,6 +400,7 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
current_class_name = keywords[-4]
|
current_class_name = keywords[-4]
|
||||||
current_arguments = []
|
current_arguments = []
|
||||||
inside_object_class = True
|
inside_object_class = True
|
||||||
|
current_class_docs = extract_doc(lines, no)
|
||||||
container_class_name = keywords[5]
|
container_class_name = keywords[5]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -337,6 +408,7 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
current_class_name = keywords[-4]
|
current_class_name = keywords[-4]
|
||||||
current_arguments = []
|
current_arguments = []
|
||||||
inside_function_class = True
|
inside_function_class = True
|
||||||
|
current_class_docs = extract_doc(lines, no)
|
||||||
container_class_name = keywords[5]
|
container_class_name = keywords[5]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -405,10 +477,21 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
for class_name, class_meta in classes.items():
|
for class_name, class_meta in classes.items():
|
||||||
output.indent()
|
output.indent()
|
||||||
output.open_custom_block("public static class", class_name, "extends", class_meta[1])
|
output.open_custom_block("public static class", class_name, "extends", class_meta[1])
|
||||||
output.newline()
|
|
||||||
|
|
||||||
for arg_type, arg_name in class_meta[2]:
|
for arg_type, arg_name, docs in class_meta[2]:
|
||||||
|
output.newline()
|
||||||
output.indent()
|
output.indent()
|
||||||
|
output.open_docs()
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
for doc in split_docs(docs):
|
||||||
|
output.write_docs(doc)
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.close_docs()
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
|
||||||
output.declare(arg_name, arg_type, "public")
|
output.declare(arg_name, arg_type, "public")
|
||||||
output.newline()
|
output.newline()
|
||||||
|
|
||||||
@ -425,24 +508,54 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
output.close_block()
|
output.close_block()
|
||||||
output.newline()
|
output.newline()
|
||||||
|
|
||||||
|
output.indent()
|
||||||
|
output.open_docs()
|
||||||
|
|
||||||
|
for doc in class_meta[3]:
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.write_docs(doc)
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.write_docs()
|
||||||
|
|
||||||
|
for arg_name, arg_type, docs in class_meta[2]:
|
||||||
|
docs = split_docs(docs)
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.write_docs(f"@param {arg_type} {arg_name} {docs[0]}")
|
||||||
|
|
||||||
|
for doc in docs[1:]:
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.write_docs()
|
||||||
|
output.fd.write(f" {doc}")
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.close_docs()
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
|
||||||
if class_meta[2]:
|
if class_meta[2]:
|
||||||
output.indent()
|
output.indent()
|
||||||
output.open_constructor_function(class_name, class_meta[2])
|
output.open_constructor_function(class_name, [(x[0], x[1]) for x in class_meta[2]])
|
||||||
output.newline()
|
output.newline()
|
||||||
|
|
||||||
for arg_type, arg_name in class_meta[2]:
|
for arg_type, arg_name, _ in class_meta[2]:
|
||||||
output.indent()
|
output.indent()
|
||||||
output.class_assign(arg_name, arg_name)
|
output.class_assign(arg_name, arg_name)
|
||||||
output.newline()
|
output.newline()
|
||||||
|
|
||||||
output.close_block(space=True)
|
output.close_block(space=True)
|
||||||
|
output.newline()
|
||||||
|
|
||||||
output.newline()
|
|
||||||
output.indent()
|
output.indent()
|
||||||
output.open_constructor_function(class_name, [("DataInput", "input")], "IOException")
|
output.open_constructor_function(class_name, [("DataInput", "input")], "IOException")
|
||||||
output.newline()
|
output.newline()
|
||||||
|
|
||||||
for arg_type, arg_name in class_meta[2]:
|
for arg_type, arg_name, _ in class_meta[2]:
|
||||||
if arg_type in natives:
|
if arg_type in natives:
|
||||||
deserialize_native(output, arg_name, arg_type)
|
deserialize_native(output, arg_name, arg_type)
|
||||||
|
|
||||||
@ -529,7 +642,7 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
output.call("output.writeInt", f"CONSTRUCTOR")
|
output.call("output.writeInt", f"CONSTRUCTOR")
|
||||||
output.newline()
|
output.newline()
|
||||||
|
|
||||||
for arg_type, arg_name in class_meta[2]:
|
for arg_type, arg_name, _ in class_meta[2]:
|
||||||
if arg_type in natives:
|
if arg_type in natives:
|
||||||
serialize_native(output, arg_type, arg_name)
|
serialize_native(output, arg_type, arg_name)
|
||||||
|
|
||||||
@ -609,6 +722,116 @@ def main(input_path: str, output_path: str, headers_path: str):
|
|||||||
output.close_block(space=True)
|
output.close_block(space=True)
|
||||||
output.close_block(space=True)
|
output.close_block(space=True)
|
||||||
|
|
||||||
|
output.close_block(space=True)
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.open_function("equals", [("java.lang.Object", "o")], "boolean")
|
||||||
|
output.newline()
|
||||||
|
|
||||||
|
output.indent()
|
||||||
|
output.open_if("this == o")
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.ret("true")
|
||||||
|
output.newline()
|
||||||
|
output.close_block(space=True)
|
||||||
|
|
||||||
|
output.indent()
|
||||||
|
output.open_if("o == null || getClass() != o.getClass()")
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.ret("false")
|
||||||
|
output.newline()
|
||||||
|
output.close_block(space=True)
|
||||||
|
|
||||||
|
if class_meta[2]:
|
||||||
|
output.indent()
|
||||||
|
other_class = class_name[0].lower() + class_name[1:]
|
||||||
|
output.local_assign(class_name, other_class, f"({class_name}) o")
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
|
||||||
|
for arg_type, arg_name, _ in class_meta[2]:
|
||||||
|
output.indent()
|
||||||
|
|
||||||
|
if arg_type in cmp_natives:
|
||||||
|
output.open_if(f"this.{arg_name} != {other_class}.{arg_name}")
|
||||||
|
|
||||||
|
elif not arg_type.endswith("[]"):
|
||||||
|
output.open_if(f"!Objects.equals(this.{arg_name}, {other_class}.{arg_name})")
|
||||||
|
|
||||||
|
elif arg_type.endswith("[][]"):
|
||||||
|
output.open_if(f"!Arrays.deepEquals(this.{arg_name}, {other_class}.{arg_name})")
|
||||||
|
|
||||||
|
else:
|
||||||
|
output.open_if(f"!Arrays.equals(this.{arg_name}, {other_class}.{arg_name})")
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.ret("false")
|
||||||
|
output.newline()
|
||||||
|
output.close_block(space=True)
|
||||||
|
|
||||||
|
output.indent()
|
||||||
|
output.ret("true")
|
||||||
|
output.newline()
|
||||||
|
|
||||||
|
output.close_block(space=True)
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
output.open_function("hashCode", [], "int")
|
||||||
|
output.newline()
|
||||||
|
|
||||||
|
output.indent()
|
||||||
|
|
||||||
|
if class_meta[2]:
|
||||||
|
primitives = [(t, n) for t, n, _ in class_meta[2] if t in cmp_natives]
|
||||||
|
|
||||||
|
if primitives and len(class_meta[2]) == 1:
|
||||||
|
output.ret(f"{native_to_object[primitives[0][0]]}.hashCode(this.{primitives[0][1]})")
|
||||||
|
|
||||||
|
elif primitives:
|
||||||
|
output.local_assign("int", "result",
|
||||||
|
f"{native_to_object[primitives[0][0]]}.hashCode(this.{primitives[0][1]})")
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
|
||||||
|
for arg_type, arg_name in primitives[1:]:
|
||||||
|
output.assign("result", f"result * 31 + "
|
||||||
|
f"{native_to_object[arg_type]}.hashCode(this.{arg_name})")
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
|
||||||
|
tdapi = [(t, n) for t, n, _ in class_meta[2] if n not in [p[1] for p in primitives]]
|
||||||
|
|
||||||
|
if tdapi and len(class_meta[2]) == 1:
|
||||||
|
output.ret(hash_object(f"this.{tdapi[0][1]}", tdapi[0][0]))
|
||||||
|
start = 1
|
||||||
|
|
||||||
|
else:
|
||||||
|
if not primitives:
|
||||||
|
output.local_assign("int", "result", hash_object(f'this.{tdapi[0][1]}', tdapi[0][0]))
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
start = 1
|
||||||
|
else:
|
||||||
|
start = 0
|
||||||
|
|
||||||
|
for arg_type, arg_name in tdapi[start:]:
|
||||||
|
output.assign("result", f"result * 31 + ({hash_object(f'this.{arg_name}', arg_type)})")
|
||||||
|
output.newline()
|
||||||
|
output.indent()
|
||||||
|
|
||||||
|
if len(class_meta[2]) > 1:
|
||||||
|
output.ret("result")
|
||||||
|
|
||||||
|
else:
|
||||||
|
output.ret("CONSTRUCTOR")
|
||||||
|
|
||||||
|
output.newline()
|
||||||
|
|
||||||
output.close_block(space=True)
|
output.close_block(space=True)
|
||||||
output.close_block(space=True)
|
output.close_block(space=True)
|
||||||
output.newline()
|
output.newline()
|
||||||
|
@ -19,6 +19,18 @@ class CodeWriter:
|
|||||||
self.fd.write(" ".join(blocks) + " {")
|
self.fd.write(" ".join(blocks) + " {")
|
||||||
self.indent_depth += 1
|
self.indent_depth += 1
|
||||||
|
|
||||||
|
def open_docs(self):
|
||||||
|
self.fd.write("/**")
|
||||||
|
|
||||||
|
def write_docs(self, text: str = ""):
|
||||||
|
if text.strip() != "":
|
||||||
|
self.fd.write(f" * {text}")
|
||||||
|
else:
|
||||||
|
self.fd.write(" *")
|
||||||
|
|
||||||
|
def close_docs(self):
|
||||||
|
self.fd.write(" */")
|
||||||
|
|
||||||
def class_assign(self, class_value, local_value):
|
def class_assign(self, class_value, local_value):
|
||||||
self.fd.write("this." + class_value + " = " + local_value + ";")
|
self.fd.write("this." + class_value + " = " + local_value + ";")
|
||||||
|
|
||||||
@ -60,6 +72,9 @@ class CodeWriter:
|
|||||||
def local_assign(self, object_type: str, name: str, value: str):
|
def local_assign(self, object_type: str, name: str, value: str):
|
||||||
self.fd.write(object_type + " " + name + " = " + value + ";")
|
self.fd.write(object_type + " " + name + " = " + value + ";")
|
||||||
|
|
||||||
|
def assign(self, name: str, value: str):
|
||||||
|
self.fd.write(name + " = " + value + ";")
|
||||||
|
|
||||||
def open_for(self, start: str, cond: str, stmt: str):
|
def open_for(self, start: str, cond: str, stmt: str):
|
||||||
self.indent_depth += 1
|
self.indent_depth += 1
|
||||||
self.fd.write("for (" + start + "; " + cond + "; " + stmt + ") {")
|
self.fd.write("for (" + start + "; " + cond + "; " + stmt + ") {")
|
||||||
|
25
headers.txt
25
headers.txt
@ -6,36 +6,13 @@ import java.lang.IllegalStateException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
public class TdApi {
|
public class TdApi {
|
||||||
public abstract static class Object {
|
public abstract static class Object {
|
||||||
public native String toString();
|
public native String toString();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(java.lang.Object o) {
|
|
||||||
if (o == null) return false;
|
|
||||||
if (o == this) return true;
|
|
||||||
if (o instanceof TdApi.Object) {
|
|
||||||
try {
|
|
||||||
return Arrays.equals(this.serialize(), ((TdApi.Object) o).serialize());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
try {
|
|
||||||
return Arrays.hashCode(this.serialize());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract int getConstructor();
|
public abstract int getConstructor();
|
||||||
|
|
||||||
public byte[] serialize() throws IOException {
|
public byte[] serialize() throws IOException {
|
||||||
|
Loading…
Reference in New Issue
Block a user