Rewrite in java
This commit is contained in:
parent
52c91733b5
commit
0a3021247d
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
*.java
|
||||
*.class
|
||||
.idea/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
venv/
|
||||
/tdlib-serializer.iml
|
||||
*.j
|
||||
/out/
|
||||
|
943
__main__.py
943
__main__.py
@ -1,943 +0,0 @@
|
||||
import sys
|
||||
import typing
|
||||
import re
|
||||
|
||||
from collections import OrderedDict
|
||||
from code_writer import CodeWriter
|
||||
|
||||
|
||||
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 chunker(seq, size):
|
||||
return (seq[pos:pos + size] for pos in range(0, len(seq), size))
|
||||
|
||||
|
||||
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)
|
||||
|
||||
if len(result) > 1 and len(result[-1].split(" ")) < 3:
|
||||
result[-2] += f" {result[-1]}"
|
||||
del result[-1]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def extract_doc(lines: typing.List[str], line: int) -> typing.List[str]:
|
||||
look_back = 2
|
||||
line = next(
|
||||
n
|
||||
for n in range(line - look_back, 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):
|
||||
if null_check:
|
||||
output.indent()
|
||||
output.open_if("input.readBoolean()")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
|
||||
if arg_type in cont:
|
||||
output.open_switch("input.readInt()")
|
||||
output.newline()
|
||||
|
||||
for class_name, class_meta in classes.items():
|
||||
if class_meta[1] == arg_type and class_name != arg_type:
|
||||
output.indent()
|
||||
output.open_switch_case(f"{class_name}.CONSTRUCTOR")
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.class_assign(arg_name, f"new {class_name}(input)")
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.switch_break()
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_switch_default()
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.exception("UnsupportedOperationException")
|
||||
output.newline()
|
||||
output.indent_depth -= 1
|
||||
|
||||
output.close_block(space=True)
|
||||
|
||||
else:
|
||||
output.open_if(f"{arg_type}.CONSTRUCTOR != input.readInt()")
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.exception("UnsupportedOperationException")
|
||||
|
||||
output.newline()
|
||||
output.close_block(space=True)
|
||||
|
||||
output.indent()
|
||||
output.class_assign(arg_name, f"new {arg_type}(input)")
|
||||
output.newline()
|
||||
|
||||
if null_check:
|
||||
output.close_block(space=True)
|
||||
|
||||
|
||||
def deserialize_native(output: CodeWriter, arg_name, arg_type, null_check: bool = True):
|
||||
if arg_type == "int":
|
||||
output.indent()
|
||||
output.class_assign(arg_name, "input.readInt()")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "byte[]" or arg_type == "byte":
|
||||
if null_check:
|
||||
output.indent()
|
||||
output.open_if("input.readBoolean()")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.class_assign(arg_name, f"new byte[input.readInt()]")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("input.readFully", f"this.{arg_name}")
|
||||
output.newline()
|
||||
|
||||
if null_check:
|
||||
output.close_block(space=True)
|
||||
|
||||
if arg_type == "long":
|
||||
output.indent()
|
||||
output.class_assign(arg_name, "input.readLong()")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "double":
|
||||
output.indent()
|
||||
output.class_assign(arg_name, "input.readDouble()")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "boolean":
|
||||
output.indent()
|
||||
output.class_assign(arg_name, "input.readBoolean()")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "String":
|
||||
if null_check:
|
||||
output.indent()
|
||||
output.open_if("input.readBoolean()")
|
||||
output.newline()
|
||||
|
||||
tmp_name = arg_name.split("[")[0] + "Tmp"
|
||||
output.indent()
|
||||
output.local_assign("byte[]", tmp_name, f"new byte[input.readInt()]")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("input.readFully", tmp_name)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.class_assign(arg_name, f"new String({tmp_name}, StandardCharsets.UTF_8)")
|
||||
output.newline()
|
||||
|
||||
if null_check:
|
||||
output.close_block(space=True)
|
||||
|
||||
|
||||
def serialize_tdapi(output: CodeWriter, arg_name, null_check: bool = True):
|
||||
if null_check:
|
||||
output.indent()
|
||||
output.open_if(f"this.{arg_name} == null")
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "false")
|
||||
output.newline()
|
||||
|
||||
output.open_if_else(space=True)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "true")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call(f"this.{arg_name}.serialize", "output")
|
||||
|
||||
output.newline()
|
||||
|
||||
if null_check:
|
||||
output.close_block(space=True)
|
||||
|
||||
|
||||
def serialize_native(output: CodeWriter, arg_type: str, arg_name: str, null_check: bool = True):
|
||||
if arg_type == "int":
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"this.{arg_name}")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "byte[]" or arg_type == "byte":
|
||||
if null_check:
|
||||
output.indent()
|
||||
output.open_if(f"this.{arg_name} == null")
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "false")
|
||||
output.newline()
|
||||
|
||||
output.open_if_else(space=True)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "true")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"this.{arg_name}.length")
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.call("output.write", f"this.{arg_name}")
|
||||
output.newline()
|
||||
|
||||
if null_check:
|
||||
output.close_block(space=True)
|
||||
|
||||
if arg_type == "long":
|
||||
output.indent()
|
||||
output.call("output.writeLong", f"this.{arg_name}")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "double":
|
||||
output.indent()
|
||||
output.call("output.writeDouble", f"this.{arg_name}")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "boolean":
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", f"this.{arg_name}")
|
||||
output.newline()
|
||||
|
||||
if arg_type == "String":
|
||||
if null_check:
|
||||
output.indent()
|
||||
output.open_if(f"this.{arg_name} == null")
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "false")
|
||||
output.newline()
|
||||
|
||||
output.open_if_else(space=True)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "true")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
tmp_name = arg_name.split("[")[0] + "Tmp"
|
||||
output.local_assign("byte[]", tmp_name, f"this.{arg_name}.getBytes(StandardCharsets.UTF_8)")
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"{tmp_name}.length")
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.call("output.write", tmp_name)
|
||||
output.newline()
|
||||
|
||||
if null_check:
|
||||
output.close_block(space=True)
|
||||
|
||||
def remove_parentheses(s):
|
||||
return re.sub(r'\<[^<>]*\>', '', s)
|
||||
|
||||
|
||||
def main(input_path: str, output_path: str, headers_path: str, java17: str):
|
||||
data_input = open(input_path)
|
||||
|
||||
java17 = java17 == "true"
|
||||
|
||||
package: typing.Optional[str] = None
|
||||
current_constructor: typing.Optional[int] = None
|
||||
current_class_name: typing.Optional[str] = None
|
||||
inside_abstract_class: bool = False
|
||||
inside_object_class: bool = False
|
||||
inside_function_class: bool = False
|
||||
inside_object_container_class: bool = False
|
||||
container_class_name: typing.Optional[str] = None
|
||||
current_class_docs: typing.Optional[typing.List[str]] = None
|
||||
function_depth: int = 0
|
||||
|
||||
function_classes = OrderedDict()
|
||||
# key: {class_name, value: (constructor_id, container_name, [arg_type, arg_name], docs)}
|
||||
|
||||
object_classes = OrderedDict()
|
||||
# key: {class_name, value: (constructor_id, container_name, [arg_type, arg_name], docs)}
|
||||
|
||||
container_classes: typing.List[str] = OrderedDict()
|
||||
# key: {class_name, value: (docs)}
|
||||
|
||||
current_arguments: typing.Optional[typing.List[typing.Tuple[str, str, typing.List[str]]]] = None
|
||||
# [(arg_name, arg_type), ...]
|
||||
|
||||
lines = list(map(remove_parentheses, map(str.strip, data_input.readlines())))
|
||||
|
||||
for no, line in enumerate(lines):
|
||||
keywords = line.split()
|
||||
|
||||
if not keywords:
|
||||
continue
|
||||
|
||||
if (inside_object_class or inside_function_class) and keywords[-1] == "{":
|
||||
function_depth += 1
|
||||
continue
|
||||
|
||||
if (inside_object_class or inside_function_class) and keywords[-1] == "}" and function_depth > 0:
|
||||
function_depth -= 1
|
||||
continue
|
||||
|
||||
if function_depth > 0:
|
||||
continue
|
||||
|
||||
if inside_object_container_class and keywords[-1] == "}":
|
||||
inside_object_container_class = False
|
||||
container_classes[current_class_name] = (current_class_docs)
|
||||
current_class_name = None
|
||||
continue
|
||||
|
||||
if inside_abstract_class and keywords[-1] == "}":
|
||||
inside_abstract_class = False
|
||||
continue
|
||||
|
||||
if inside_object_class and keywords[-1] == "}":
|
||||
inside_object_class = False
|
||||
object_classes[current_class_name] = (current_constructor, container_class_name,
|
||||
current_arguments, current_class_docs)
|
||||
container_class_name = None
|
||||
current_arguments = None
|
||||
current_class_name = None
|
||||
current_constructor = None
|
||||
continue
|
||||
|
||||
if inside_function_class and keywords[0] == "}":
|
||||
inside_function_class = False
|
||||
function_classes[current_class_name] = (current_constructor, container_class_name,
|
||||
current_arguments, current_class_docs)
|
||||
current_arguments = None
|
||||
container_class_name = None
|
||||
current_class_name = None
|
||||
current_constructor = None
|
||||
continue
|
||||
|
||||
if inside_function_class or inside_object_class:
|
||||
if len(keywords) == 3 and keywords[-1].endswith(";"):
|
||||
current_arguments.append((keywords[1], keywords[2][:-1], extract_doc(lines, no)))
|
||||
continue
|
||||
|
||||
if len(keywords) == 7 and keywords[4] == "CONSTRUCTOR":
|
||||
current_constructor = int(keywords[6][:-1])
|
||||
continue
|
||||
|
||||
if keywords[0] == "package":
|
||||
package = line
|
||||
continue
|
||||
|
||||
if len(keywords) == 8 and keywords[1] == "abstract":
|
||||
inside_object_container_class = True
|
||||
current_class_name = keywords[4]
|
||||
current_class_docs = extract_doc(lines, no)
|
||||
continue
|
||||
|
||||
if len(keywords) == 4 and keywords[2] == "TdApi":
|
||||
continue
|
||||
|
||||
if len(keywords) == 6 and keywords[1] == "abstract":
|
||||
inside_abstract_class = True
|
||||
continue
|
||||
|
||||
if len(keywords) == 7 and keywords[2] == "class" and keywords[5] == "Object":
|
||||
current_class_name = keywords[-4]
|
||||
current_arguments = []
|
||||
inside_object_class = True
|
||||
current_class_docs = extract_doc(lines, no)
|
||||
container_class_name = keywords[5]
|
||||
continue
|
||||
|
||||
if len(keywords) == 7 and keywords[2] == "class" and keywords[5] == "Function":
|
||||
current_class_name = keywords[-4]
|
||||
current_arguments = []
|
||||
inside_function_class = True
|
||||
current_class_docs = extract_doc(lines, no)
|
||||
container_class_name = keywords[5]
|
||||
continue
|
||||
|
||||
if len(keywords) == 7 and keywords[2] == "class" and keywords[5] in container_classes:
|
||||
current_class_name = keywords[-4]
|
||||
current_arguments = []
|
||||
inside_object_class = True
|
||||
current_class_docs = extract_doc(lines, no)
|
||||
container_class_name = keywords[5]
|
||||
continue
|
||||
|
||||
data_input.close()
|
||||
|
||||
data_output = open(output_path, "w")
|
||||
data_output.write(package + "\n\n")
|
||||
data_output.write(open(headers_path).read())
|
||||
del container_classes["Function"]
|
||||
|
||||
output = CodeWriter(data_output, 1)
|
||||
|
||||
output.indent()
|
||||
output.open_custom_block(f"public static class Deserializer")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_function("deserialize", [("DataInput", "input")], "static Object", "IOException")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_switch("input.readInt()")
|
||||
output.newline()
|
||||
|
||||
for classes in (object_classes, function_classes):
|
||||
for class_name in classes.keys():
|
||||
output.indent()
|
||||
output.open_switch_case(f"{class_name}.CONSTRUCTOR")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.ret(f"new {class_name}(input)")
|
||||
output.newline()
|
||||
|
||||
output.indent_depth -= 1
|
||||
|
||||
output.indent()
|
||||
output.open_switch_default()
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.exception("UnsupportedOperationException")
|
||||
output.newline()
|
||||
output.indent_depth -= 1
|
||||
|
||||
output.close_block(space=True)
|
||||
output.close_block(space=True)
|
||||
output.close_block(space=True)
|
||||
|
||||
output.newline()
|
||||
|
||||
for container_class_name, container_class_meta in container_classes.items():
|
||||
output.indent()
|
||||
output.open_docs()
|
||||
|
||||
for docs in [container_class_meta[0]]:
|
||||
for doc in split_docs([docs]):
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.write_docs(doc)
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.close_docs()
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
|
||||
allowed_classess = []
|
||||
|
||||
for classes in (object_classes, function_classes):
|
||||
for class_name, class_meta in classes.items():
|
||||
if container_class_name == class_meta[1]:
|
||||
allowed_classess.append(class_name)
|
||||
|
||||
allowed_classess_str = "permits "
|
||||
|
||||
for i, allowed_classess_group in enumerate(chunker(allowed_classess, 3)):
|
||||
if i:
|
||||
allowed_classess_str += ",\n"
|
||||
allowed_classess_str += output.indent_chr * (output.indent_depth + 1)
|
||||
allowed_classess_str += ", ".join(allowed_classess_group)
|
||||
|
||||
if allowed_classess and java17:
|
||||
output.open_custom_block(f"public abstract static sealed class", container_class_name, "extends Object", allowed_classess_str)
|
||||
else:
|
||||
output.open_custom_block(f"public abstract static class", container_class_name, "extends Object")
|
||||
|
||||
output.close_block()
|
||||
output.newline()
|
||||
|
||||
for classes in (object_classes, function_classes):
|
||||
for class_name, class_meta in classes.items():
|
||||
output.indent()
|
||||
output.open_docs()
|
||||
|
||||
for docs in class_meta[3]:
|
||||
for doc in split_docs([docs]):
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.write_docs(doc)
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.close_docs()
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
|
||||
class_generics = ""
|
||||
|
||||
if class_meta[1] == "Function":
|
||||
class_generics = "<"
|
||||
class_generics += docs.split("@link ")[1].split()[0]
|
||||
class_generics += ">"
|
||||
|
||||
output.open_custom_block("public static final class", class_name, "extends", class_meta[1] + class_generics)
|
||||
|
||||
for arg_type, arg_name, docs in class_meta[2]:
|
||||
output.newline()
|
||||
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.newline()
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.declare("CONSTRUCTOR", "int", "public static final", value=str(class_meta[0]))
|
||||
output.newline()
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_docs()
|
||||
|
||||
for docs in class_meta[3]:
|
||||
for doc in split_docs([docs]):
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.write_docs(doc)
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.close_docs()
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.open_constructor_function(class_name, [])
|
||||
output.close_block()
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_docs()
|
||||
|
||||
for docs in class_meta[3]:
|
||||
for doc in split_docs([docs]):
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.write_docs(doc)
|
||||
|
||||
for arg_name, arg_type, docs in class_meta[2]:
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.write_docs()
|
||||
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]:
|
||||
output.indent()
|
||||
output.open_constructor_function(class_name, [(x[0], x[1]) for x in class_meta[2]])
|
||||
output.newline()
|
||||
|
||||
for arg_type, arg_name, _ in class_meta[2]:
|
||||
output.indent()
|
||||
output.class_assign(arg_name, arg_name)
|
||||
output.newline()
|
||||
|
||||
output.close_block(space=True)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_docs()
|
||||
|
||||
for docs in class_meta[3]:
|
||||
for doc in split_docs([docs]):
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.write_docs(doc)
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.close_docs()
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_constructor_function(class_name, [("DataInput", "input")], "IOException")
|
||||
output.newline()
|
||||
|
||||
for arg_type, arg_name, _ in class_meta[2]:
|
||||
if arg_type in natives:
|
||||
deserialize_native(output, arg_name, arg_type)
|
||||
|
||||
elif not arg_type.endswith("[]"):
|
||||
deserialize_tdapi(output, arg_name, arg_type, container_classes, object_classes)
|
||||
|
||||
elif arg_type == "byte[][]" or not arg_type.endswith("[][]"):
|
||||
output.indent()
|
||||
output.open_if("input.readBoolean()")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
if arg_type == "byte[][]":
|
||||
output.class_assign(arg_name, f"new byte[input.readInt()][]")
|
||||
else:
|
||||
output.class_assign(arg_name, f"new {arg_type[:-2]}[input.readInt()]")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_for("int i = 0", f"i < this.{arg_name}.length", "i++")
|
||||
output.newline()
|
||||
|
||||
if arg_type[:-2] in natives:
|
||||
deserialize_native(output, f"{arg_name}[i]", arg_type[:-2], null_check=False)
|
||||
|
||||
else:
|
||||
deserialize_tdapi(output, f"{arg_name}[i]", arg_type[:-2],
|
||||
container_classes, object_classes, null_check=False)
|
||||
|
||||
output.close_block(space=True)
|
||||
output.close_block(space=True)
|
||||
|
||||
elif arg_type.endswith("[][]"):
|
||||
output.indent()
|
||||
output.open_if("input.readBoolean()")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.class_assign(arg_name, f"new {arg_type[:-4]}[input.readInt()][]")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_for("int i = 0", f"i < this.{arg_name}.length", "i++")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.class_assign(f"{arg_name}[i]", f"new {arg_type[:-4]}[input.readInt()]")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_for("int j = 0", f"j < this.{arg_name}[i].length", "j++")
|
||||
output.newline()
|
||||
|
||||
if arg_type[:-4] in natives:
|
||||
deserialize_native(output, f"{arg_name}[i][j]", arg_type[:-4], null_check=False)
|
||||
|
||||
else:
|
||||
deserialize_tdapi(output, f"{arg_name}[i][j]", arg_type[:-4],
|
||||
container_classes, object_classes, null_check=False)
|
||||
|
||||
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("getConstructor", [], "int")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.ret("CONSTRUCTOR")
|
||||
output.newline()
|
||||
|
||||
output.close_block(space=True)
|
||||
|
||||
output.newline()
|
||||
output.indent()
|
||||
output.open_function("serialize", [("DataOutput", "output")], "void", "IOException")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"CONSTRUCTOR")
|
||||
output.newline()
|
||||
|
||||
for arg_type, arg_name, _ in class_meta[2]:
|
||||
if arg_type in natives:
|
||||
serialize_native(output, arg_type, arg_name)
|
||||
|
||||
elif not arg_type.endswith("[]"):
|
||||
serialize_tdapi(output, arg_name)
|
||||
|
||||
elif arg_type == "byte[][]" or not arg_type.endswith("[][]"):
|
||||
output.indent()
|
||||
output.open_if(f"this.{arg_name} == null")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "false")
|
||||
output.newline()
|
||||
|
||||
output.open_if_else(space=True)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "true")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"this.{arg_name}.length")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_for("int i = 0", f"i < this.{arg_name}.length", "i++")
|
||||
output.newline()
|
||||
|
||||
if arg_type[:-2] in natives:
|
||||
serialize_native(output, arg_type[:-2], f"{arg_name}[i]", null_check=False)
|
||||
else:
|
||||
serialize_tdapi(output, f"{arg_name}[i]", null_check=False)
|
||||
|
||||
output.close_block(space=True)
|
||||
output.close_block(space=True)
|
||||
|
||||
elif arg_type.endswith("[][]"):
|
||||
output.indent()
|
||||
output.open_if(f"this.{arg_name} == null")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "false")
|
||||
output.newline()
|
||||
|
||||
output.open_if_else(space=True)
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeBoolean", "true")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"this.{arg_name}.length")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_for("int i = 0", f"i < this.{arg_name}.length", "i++")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.call("output.writeInt", f"this.{arg_name}[i].length")
|
||||
output.newline()
|
||||
|
||||
output.indent()
|
||||
output.open_for("int j = 0", f"j < this.{arg_name}[i].length", "j++")
|
||||
output.newline()
|
||||
|
||||
if arg_type[:-4] in natives:
|
||||
serialize_native(output, arg_type[:-4], f"{arg_name}[i][j]", null_check=False)
|
||||
else:
|
||||
serialize_tdapi(output, f"{arg_name}[i][j]", null_check=False)
|
||||
|
||||
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.newline()
|
||||
|
||||
data_output.seek(data_output.tell() - 1)
|
||||
data_output.write("}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[-4], sys.argv[-3], sys.argv[-2], sys.argv[-1])
|
151
code_writer.py
151
code_writer.py
@ -1,151 +0,0 @@
|
||||
import typing
|
||||
|
||||
|
||||
indent = "\t"
|
||||
|
||||
|
||||
class CodeWriter:
|
||||
fd: typing.TextIO
|
||||
indent_depth: int
|
||||
indent_chr = indent
|
||||
|
||||
def split_args(self, args: str) -> typing.List[str]:
|
||||
tokens = args.split(", ")
|
||||
result = [tokens[0]]
|
||||
|
||||
for token in tokens[1:]:
|
||||
if len(", ".join(result[-1]) + token) < 120:
|
||||
result[-1] += f", {token}"
|
||||
else:
|
||||
result.append(token)
|
||||
|
||||
if len(result) > 1 and len(result[-1].split(", ")) < 3:
|
||||
result[-2] += f", {result[-1]}"
|
||||
del result[-1]
|
||||
|
||||
return result
|
||||
|
||||
def __init__(self, file: typing.TextIO, indent_depth: int = 0):
|
||||
self.fd = file
|
||||
self.indent_depth = indent_depth
|
||||
|
||||
def indent(self):
|
||||
self.fd.write(indent * self.indent_depth)
|
||||
|
||||
def open_custom_block(self, *blocks: str):
|
||||
self.fd.write(" ".join(blocks) + " {")
|
||||
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):
|
||||
self.fd.write("this." + class_value + " = " + local_value + ";")
|
||||
|
||||
def close_block(self, space: bool = False, newline: bool = True):
|
||||
self.indent_depth -= 1
|
||||
if space:
|
||||
self.indent()
|
||||
self.fd.write("}\n" if newline else "}")
|
||||
|
||||
def newline(self):
|
||||
self.fd.write("\n")
|
||||
|
||||
def open_switch(self, data: str):
|
||||
self.indent_depth += 1
|
||||
self.fd.write("switch(" + data + ") {")
|
||||
|
||||
def switch_break(self):
|
||||
self.indent_depth -= 1
|
||||
self.fd.write("break;")
|
||||
|
||||
def open_switch_case(self, case: str):
|
||||
self.indent_depth += 1
|
||||
self.fd.write("case " + case + ":")
|
||||
|
||||
def open_switch_default(self):
|
||||
self.indent_depth += 1
|
||||
self.fd.write("default:")
|
||||
|
||||
def exception(self, exception_class: str):
|
||||
self.fd.write("throw new " + exception_class + "();")
|
||||
|
||||
def open_if_else(self, space: bool = False):
|
||||
self.indent_depth -= 1
|
||||
if space:
|
||||
self.indent()
|
||||
self.fd.write("} else {")
|
||||
self.indent_depth += 1
|
||||
|
||||
def local_assign(self, object_type: str, name: str, value: str):
|
||||
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):
|
||||
self.indent_depth += 1
|
||||
self.fd.write("for (" + start + "; " + cond + "; " + stmt + ") {")
|
||||
|
||||
def open_if(self, cond: str):
|
||||
self.indent_depth += 1
|
||||
self.fd.write("if (" + cond + ") {")
|
||||
|
||||
def call(self, method: str, *args: str):
|
||||
self.fd.write(method + "(" + ", ".join(args) + ");")
|
||||
|
||||
def ret(self, var: str):
|
||||
self.fd.write("return " + var + ";")
|
||||
|
||||
def open_function(self, name: str, args: typing.List[typing.Tuple[str, str]], t: str, e: str = None):
|
||||
self.indent_depth += 1
|
||||
result = "public " + t + " " + name + "(" + ", ".join((t + " " + n for t, n in args)) + ")"
|
||||
if e:
|
||||
result += " throws " + e
|
||||
result += " {"
|
||||
self.fd.write(result)
|
||||
|
||||
def open_constructor_function(self, name: str, args: typing.List[typing.Tuple[str, str]], e: str = None):
|
||||
self.indent_depth += 1
|
||||
result = "public " + name + "("
|
||||
|
||||
result_args = ", ".join((t + " " + n for t, n in args))
|
||||
|
||||
if len(result_args) > 60:
|
||||
result_args = result_args.split(", ")
|
||||
|
||||
for i, result_arg in enumerate(result_args):
|
||||
if i:
|
||||
result += (self.indent_depth + 1) * indent
|
||||
|
||||
result += result_arg
|
||||
|
||||
if i != len(result_args) - 1:
|
||||
result += ",\n"
|
||||
else:
|
||||
result += result_args
|
||||
|
||||
result += ")"
|
||||
|
||||
if e:
|
||||
result += " throws " + e
|
||||
|
||||
result += " {"
|
||||
|
||||
self.fd.write(result)
|
||||
|
||||
def declare(self, name: str, typ: str, flags: str, value: str = None):
|
||||
result = flags + " " + typ + " " + name
|
||||
if value:
|
||||
result += " = " + value
|
||||
result += ";"
|
||||
self.fd.write(result)
|
@ -1,2 +0,0 @@
|
||||
wget https://git.ignuranza.net/andreacavalli/JTDLib/raw/branch/master/src/main/java/it/ernytech/tdlib/TdApi.java -O TdApi.java
|
||||
python3 . TdApi.java headers.txt
|
1000
transform.java
Normal file
1000
transform.java
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user