Make gen init header code shared

This commit is contained in:
ChillerDragon 2023-05-14 10:41:05 +02:00
parent 4801af9c59
commit 37ec4349aa

View file

@ -79,14 +79,10 @@ class NetMessageJson(TypedDict):
members: list[NetMessageMemberJson]
attributes: list[Literal['msg_encoding']]
class NetConnlessMemberJson(TypedDict):
name: list[str]
type: NetConnlessMemberTypeJson
class NetConnlessJson(TypedDict):
id: Annotated[list[int], 8]
name: list[str]
members: list[NetConnlessMemberJson]
members: list[NetMessageMemberJson]
class SpecJson(TypedDict):
constants: list[ConstantJson]
@ -489,7 +485,7 @@ def gen_pack_return(msg: NetMessageJson) -> str:
return f" return {pack_field(members[0])} + \\\n" + \
' + \\\n'.join(mem_strs)
def pack_field_connless7(member: NetConnlessMemberJson) -> str:
def pack_field_connless7(member: NetMessageMemberJson) -> str:
name: str = name_to_snake(member["name"])
field: str = f'self.{name}'
packer = 'int'
@ -510,7 +506,7 @@ def pack_field_connless7(member: NetConnlessMemberJson) -> str:
return f'pack_{packer}({field})'
def gen_pack_return_connless7(msg: NetConnlessJson) -> str:
members: list[NetConnlessMemberJson] = msg['members']
members: list[NetMessageMemberJson] = msg['members']
if len(members) == 0:
return " return b''"
if len(members) == 1:
@ -559,6 +555,129 @@ class CodeGenerator():
def __init__(self) -> None:
self.game_enums: list[GameEnumJson] = []
def gen_init_member_header_def(
self,
member: NetMessageMemberJson,
name_snake: str,
message_type: Literal['game', 'system', 'connless']
) -> list[str]:
"""
get_init_member_header_def
given a member field it returns an array of strings
that represent the python code for the content in the
init method parameter list
def __init__(self, [THIS IS GENERATED]) -> None:
it might return two fields for members like data
that also introduce a size field
the returned assignements do not include indentation
"""
args: list[str] = []
# {
# 'name': ['message'],
# 'type': {
# 'kind': 'string',
# 'disallow_cc': False
# }
# }
ftype = 'int'
default = '-1'
if member['type']['kind'] == 'string':
ftype = 'str'
default = "'default'"
elif member['type']['kind'] == 'packed_addresses': # TODO: packed_addreses default value
ftype = 'list[MastersrvAddr]'
default = '[]'
elif member['type']['kind'] == 'serverinfo_client': # TODO: serverinfo_client
ftype = 'bytes'
default = "b''"
elif member['type']['kind'] == 'be_uint16':
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'uint8':
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'rest':
ftype = 'bytes'
default = "b'\\x00'"
elif member['type']['kind'] == 'sha256':
ftype = 'Annotated[bytes, 32]'
default = "bytes(32)"
elif member['type']['kind'] == 'data':
ftype = 'bytes'
default = "b'\\x00'"
if member['type']['size'] == 'specified_before':
args.append('data_size: Optional[int] = None')
else:
raise ValueError(f"Error: unknown data size {member['type']}")
# {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}},
elif member['type']['kind'] == 'enum':
enum_name: str = name_to_camel(member['type']['enum'])
ftype = 'int'
default = self.get_default_enum7(enum_name)
default = f"enum7.{default}.value"
elif member['type']['kind'] in ('int32', 'tick'):
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'boolean':
ftype = 'bool'
default = 'False'
elif member['type']['kind'] == 'tune_param':
ftype = 'float'
default = '0.0'
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'array':
size: int = member['type']['count']
if size is None:
print("Error: size is none for the following member")
print(member)
exit(1)
arr_member: ArrayMemberTypeJson = member['type']['member_type']
if arr_member['kind'] == 'string':
ftype = f'Annotated[list[str], {size}]'
default = '[' + ', '.join(["''"] * size) + ']'
elif arr_member['kind'] == 'boolean':
ftype = f'Annotated[list[bool], {size}]'
default = '[' + ', '.join(["False"] * size) + ']'
elif arr_member['kind'] in ('int32', 'tick', 'enum'):
ftype = f'Annotated[list[int], {size}]'
default = '[' + ', '.join(["0"] * size) + ']'
else:
raise ValueError( \
f"Error: unknown array member type {member['type']}")
# Initializing lists with defaults
# And type annotation can get quite long
# So split it in two lines
default = f'\\\n {default}'
elif member['type']['kind'] == 'flags': # TODO: think about flags
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string':
ftype = 'str'
default = "''"
elif member['type']['inner']['kind'] in ('int32', 'tick'):
ftype = 'int'
default = '0'
else:
raise \
ValueError( \
f"Error: unknown optional type {member['type']}")
else:
raise ValueError(f"Error: unknown type {member['type']}")
name = name_to_snake(member["name"])
manual_default = get_default(f"{message_type}.{name_snake}.{name}")
if manual_default:
default = manual_default
args.append(f'{name}: {ftype} = {default}')
return args
def write_init_method_header_connless7(
self,
out_file: TextIO,
@ -573,33 +692,9 @@ class CodeGenerator():
f' self{comma}')
args: list[str] = []
for member in msg['members']:
ftype = 'int'
default = '-1'
if member['type']['kind'] == 'packed_addresses': # TODO: packed_addreses default value
ftype = 'list[MastersrvAddr]'
default = '[]'
elif member['type']['kind'] == 'serverinfo_client': # TODO: serverinfo_client
ftype = 'bytes'
default = "b''"
elif member['type']['kind'] == 'be_uint16':
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'uint8':
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'int32':
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'string':
ftype = 'str'
default = "'default'"
else:
raise ValueError(f"Error: unknown type {member['type']}")
name = name_to_snake(member["name"])
manual_default = get_default(f"connless.{name_snake}.{name}")
if manual_default:
default = manual_default
args.append(f' {name}: {ftype} = {default}')
mem_defs: list[str] = self.gen_init_member_header_def(member, name_snake, 'connless')
for mem_def in mem_defs:
args.append(f' {mem_def}')
out_file.write(',\n'.join(args) + '\n')
out_file.write(' ) -> None:\n')
@ -619,94 +714,9 @@ class CodeGenerator():
f' chunk_header: ChunkHeader = ChunkHeader(){comma}')
args: list[str] = []
for member in msg['members']:
# {
# 'name': ['message'],
# 'type': {
# 'kind': 'string',
# 'disallow_cc': False
# }
# }
ftype = 'int'
default = '-1'
if member['type']['kind'] == 'string':
ftype = 'str'
default = "'default'"
elif member['type']['kind'] == 'rest':
ftype = 'bytes'
default = "b'\\x00'"
elif member['type']['kind'] == 'sha256':
ftype = 'Annotated[bytes, 32]'
default = "bytes(32)"
elif member['type']['kind'] == 'data':
ftype = 'bytes'
default = "b'\\x00'"
if member['type']['size'] == 'specified_before':
args.append(' data_size: Optional[int] = None')
else:
raise ValueError(f"Error: unknown data size {member['type']}")
# {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}},
elif member['type']['kind'] == 'enum':
enum_name: str = name_to_camel(member['type']['enum'])
ftype = 'int'
default = self.get_default_enum7(enum_name)
default = f"enum7.{default}.value"
elif member['type']['kind'] in ('int32', 'tick'):
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'boolean':
ftype = 'bool'
default = 'False'
elif member['type']['kind'] == 'tune_param':
ftype = 'float'
default = '0.0'
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'array':
size: int = member['type']['count']
if size is None:
print("Error: size is none for the following message")
print(msg)
exit(1)
arr_member: ArrayMemberTypeJson = member['type']['member_type']
if arr_member['kind'] == 'string':
ftype = f'Annotated[list[str], {size}]'
default = '[' + ', '.join(["''"] * size) + ']'
elif arr_member['kind'] == 'boolean':
ftype = f'Annotated[list[bool], {size}]'
default = '[' + ', '.join(["False"] * size) + ']'
elif arr_member['kind'] in ('int32', 'tick', 'enum'):
ftype = f'Annotated[list[int], {size}]'
default = '[' + ', '.join(["0"] * size) + ']'
else:
raise ValueError( \
f"Error: unknown array member type {member['type']}")
# Initializing lists with defaults
# And type annotation can get quite long
# So split it in two lines
default = f'\\\n {default}'
elif member['type']['kind'] == 'flags': # TODO: think about flags
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string':
ftype = 'str'
default = "''"
elif member['type']['inner']['kind'] in ('int32', 'tick'):
ftype = 'int'
default = '0'
else:
raise \
ValueError( \
f"Error: unknown optional type {member['type']}")
else:
raise ValueError(f"Error: unknown type {member['type']}")
name = name_to_snake(member["name"])
manual_default = get_default(f"{game}.{name_snake}.{name}")
if manual_default:
default = manual_default
args.append(f' {name}: {ftype} = {default}')
mem_defs: list[str] = self.gen_init_member_header_def(member, name_snake, game)
for mem_def in mem_defs:
args.append(f' {mem_def}')
out_file.write(',\n'.join(args) + '\n')
out_file.write(' ) -> None:\n')