Fix optional type assuming int

This commit is contained in:
ChillerDragon 2023-04-02 19:56:29 +02:00
parent bffa9f70cb
commit df3fcb9b17
2 changed files with 82 additions and 22 deletions

View file

@ -10,21 +10,56 @@ class ConstantJson(TypedDict):
type: str
value: int
class GameEnumValuesJson(TypedDict):
class NetEnumValuesJson(TypedDict):
value: str
name: list[str]
class GameEnumJson(TypedDict):
class NetEnumJson(TypedDict):
name: list[str]
values: list[GameEnumValuesJson]
values: list[NetEnumValuesJson]
class GameMessageMemberTypeJson(TypedDict):
kind: str
class InnerNetMessageMemberTypeJson(TypedDict):
# TODO: define this literal as type
# so it can be reused
kind: Literal[ \
'int32', \
'tick', \
'string', \
'raw', \
'sha256', \
'data', \
'rest', \
'enum', \
'boolean', \
'tune_param', \
'snapshot_object', \
'array', \
'flags', \
'optional']
disallow_cc: bool
class NetMessageMemberTypeJson(TypedDict):
kind: Literal[ \
'int32', \
'tick', \
'string', \
'raw', \
'sha256', \
'data', \
'rest', \
'enum', \
'boolean', \
'tune_param', \
'snapshot_object', \
'array', \
'flags', \
'optional']
inner: InnerNetMessageMemberTypeJson
disallow_cc: bool
class NetMessageMemberJson(TypedDict):
name: list[str]
type: GameMessageMemberTypeJson
type: NetMessageMemberTypeJson
class NetMessageJson(TypedDict):
id: int
@ -34,7 +69,7 @@ class NetMessageJson(TypedDict):
class SpecJson(TypedDict):
constants: list[ConstantJson]
game_enumerations: list[GameEnumJson]
game_enumerations: list[NetEnumJson]
game_messages: list[NetMessageJson]
system_messages: list[NetMessageJson]
@ -167,9 +202,15 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
elif member['type']['kind'] == 'flags': # TODO: think about flags
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'optional': # TODO: think about optionals
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
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"])
@ -208,8 +249,13 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
ftype = 'int'
elif member['type']['kind'] == 'flags': # TODO: think about flags
ftype = 'int'
elif member['type']['kind'] == 'optional': # TODO: think about optionals
ftype = 'int'
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
ftype = 'str'
elif member['type']['inner']['kind'] in ('int32', 'tick'):
ftype = 'int'
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"])
@ -244,8 +290,13 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
unpacker = 'int() # TODO: this is an array'
elif member['type']['kind'] == 'flags': # TODO: think about flags
unpacker = 'int() # TODO: this is a flag'
elif member['type']['kind'] == 'optional': # TODO: think about optional
unpacker = 'int() # TODO: this is a optional of type any'
elif member['type']['kind'] == 'optional':
# TODO: unpacker should not crash on missing optional fields
# check how tw code does it and be smart here
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
unpacker = 'str() # TODO: warning this can fail because it is an optional field'
elif member['type']['inner']['kind'] in ('int32', 'tick'):
unpacker = 'int() # TODO: warning this can fail because it is an optional field'
else:
raise ValueError(f"Error: unknown type {member['type']}")
name = name_to_snake(member["name"])
@ -279,8 +330,11 @@ def get_dependencies(msg: NetMessageJson) -> str:
packer_deps.append('pack_int')
elif member['type']['kind'] == 'flags': # TODO: think about flags
packer_deps.append('pack_int')
elif member['type']['kind'] == 'optional': # TODO: think about optional
packer_deps.append('pack_int')
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string':
packer_deps.append('pack_str')
elif member['type']['inner']['kind'] in ('int32', 'tick'):
packer_deps.append('pack_int')
else:
raise ValueError(f"Error: unknown type {member['type']}")
if len(packer_deps) == 0:
@ -314,8 +368,14 @@ def pack_field(member: NetMessageMemberJson) -> str:
packer = 'int'
elif member['type']['kind'] == 'flags': # TODO: think about flags
packer = 'int'
elif member['type']['kind'] == 'optional': # TODO: think about optional
elif member['type']['kind'] == 'optional':
packer = 'int'
# TODO: unpacker should allow not packing optional fields
# check how tw code does it and be smart here
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
packer = 'str'
elif member['type']['inner']['kind'] in ('int32', 'tick'):
packer = 'int'
else:
raise ValueError(f"Error: unknown type {member['type']}")
return f'pack_{packer}({field})'

View file

@ -9,7 +9,7 @@ class MsgInfo(PrettyPrint):
def __init__(
self,
version: str = 'default',
password: int = 0,
password: str = '',
client_version: int = 0
) -> None:
self.message_name = 'info'
@ -17,7 +17,7 @@ class MsgInfo(PrettyPrint):
self.header: ChunkHeader
self.version: str = version
self.password: int = password
self.password: str = password
self.client_version: int = client_version
# first byte of data
@ -26,11 +26,11 @@ class MsgInfo(PrettyPrint):
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.version = unpacker.get_str()
self.password = unpacker.get_int() # TODO: this is a optional of type any
self.client_version = unpacker.get_int() # TODO: this is a optional of type any
self.password = unpacker.get_str() # TODO: warning this can fail because it is an optional field
self.client_version = unpacker.get_int() # TODO: warning this can fail because it is an optional field
return True
def pack(self) -> bytes:
return pack_str(self.version) + \
pack_int(self.password) + \
pack_str(self.password) + \
pack_int(self.client_version)