1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
from typing import Dict
from util import parse_param, to_camel_case, to_snake_case, SCALAR_MAPPING
from entity import Field, Struct, Enum, Method, Type, Scalar
def render(parsed, entities, log):
structs: Dict[str, Type] = dict()
enums: Dict[str, Enum] = dict()
methods: Dict[str, Method] = dict()
for (scalar, _) in SCALAR_MAPPING.values():
structs.update({scalar: Scalar(name=scalar)})
def parse_decl(decl) -> tuple: # -> (description, ctor name, fields, base name)
docs, derived, params, base = decl.children
docs = {
doc.children[0]: ''.join(doc.children[1].children)
for doc in docs.children
}
params = params.children
fields = []
for param in params:
name, raw_type = param.children
typ, inner_typ, deserializer = parse_param(raw_type)
doc = docs[name]
if name == 'description':
doc = docs['param_description']
fields.append(Field(typeid=typ, name=str(name), deserializer=deserializer, doc=doc, inner_type=inner_typ))
return docs['description'], str(derived), fields, str(base)
def find_type(name: str) -> Type:
if name in structs:
return structs[name]
elif name in enums:
return enums[name]
else:
raise ValueError(f"could not find type {name}")
parsed_decls, parsed_methods = parsed.children
for decl in parsed_decls.children:
if decl.data == 'decl':
description, type_name, fields, base_type = parse_decl(decl)
rusty_type_name = to_camel_case(type_name)
rusty_base_type = to_camel_case(base_type)
struct = Struct(name=rusty_type_name, doc=description)
structs.update({rusty_type_name: struct})
for field in fields:
struct.add_field(field)
if rusty_type_name != rusty_base_type:
enums[to_camel_case(rusty_base_type)].add_member(struct)
else:
name, doc = decl.children
rusty_name = to_camel_case(name)
doc = ''.join(doc.children[1].children)
enums[rusty_name] = Enum(name=rusty_name, doc=doc)
for decl in parsed_methods.children:
docs, name, params, ret = parse_decl(decl)
ret_typ = find_type(to_camel_case(ret))
m = Method(orig_name=name, ret=ret_typ, docs=docs)
for param in params:
param.initialize_with_type(find_type(param.inner_type))
m.add_param(param)
methods[m.name] = m
for struct in structs.values():
if isinstance(struct, Scalar):
continue
for field in struct.deps:
field.initialize_with_type(find_type(field.inner_type))
for e_name, enum in enums.items():
if e_name not in entities:
enum.exclude = True
else:
for member in enum.deps:
if len(member.deps) == 0:
member.exclude = True
else:
entities.append(member.name) # force inclusion of children
for s_name, struct in structs.items():
if s_name not in entities:
struct.exclude = True
prelude = '''
#![allow(unused)]
use serde::Deserializer;
use tdlib_rs::client::ClientLike;
use serde_derive::{Serialize, Deserialize};
use serde_json::{json, Value as SerdeJsonValue};
use tdlib_rs::Client;
use tdlib_rs::client::ResponseFuture;
use super::{deserialize_i64_0, deserialize_i64_1};
'''
print(prelude)
for s_name, struct in structs.items():
if not struct.is_excluded and s_name in entities:
struct.render_as_decl()
for e_name, enum in enums.items():
if not enum.is_excluded and e_name in entities:
enum.render_as_decl()
print('pub trait ClientExt: ClientLike {')
for m_name, meth in methods.items():
if m_name in entities:
meth.render_as_decl()
print('}')
|