Skip to content

Commit

Permalink
Infer the object ID from its TL definition when not given
Browse files Browse the repository at this point in the history
  • Loading branch information
Lonami committed Jun 30, 2017
1 parent 83c8e98 commit 79ee98a
Showing 1 changed file with 48 additions and 10 deletions.
58 changes: 48 additions & 10 deletions telethon_generator/parser/tl_object.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
from zlib import crc32


class TLObject:
Expand All @@ -24,12 +25,18 @@ def __init__(self, fullname, object_id, args, result, is_function):
self.namespace = None
self.name = fullname

# The ID should be an hexadecimal string
self.id = int(object_id, base=16)
self.args = args
self.result = result
self.is_function = is_function

# The ID should be an hexadecimal string or None to be inferred
if object_id is None:
self.id = self.infer_id()
else:
self.id = int(object_id, base=16)
assert self.id == self.infer_id(),\
'Invalid inferred ID for ' + repr(self)

@staticmethod
def from_tl(tl, is_function):
"""Returns a TL object from the given TL scheme line"""
Expand All @@ -38,8 +45,10 @@ def from_tl(tl, is_function):
match = re.match(r'''
^ # We want to match from the beginning to the end
([\w.]+) # The .tl object can contain alpha_name or namespace.alpha_name
\# # After the name, comes the ID of the object
([0-9a-f]+) # The constructor ID is in hexadecimal form
(?:
\# # After the name, comes the ID of the object
([0-9a-f]+) # The constructor ID is in hexadecimal form
)? # If no constructor ID was given, CRC32 the 'tl' to determine it
(?:\s # After that, we want to match its arguments (name:type)
{? # For handling the start of the '{X:Type}' case
Expand Down Expand Up @@ -91,16 +100,39 @@ def is_core_type(self):
(and thus should be embedded in the generated code) or not"""
return self.id in TLObject.CORE_TYPES

def __repr__(self):
def __repr__(self, ignore_id=False):
fullname = ('{}.{}'.format(self.namespace, self.name)
if self.namespace is not None else self.name)

hex_id = hex(self.id)[2:].rjust(8,
'0') # Skip 0x and add 0's for padding
if getattr(self, 'id', None) is None or ignore_id:
hex_id = ''
else:
# Skip 0x and add 0's for padding
hex_id = '#' + hex(self.id)[2:].rjust(8, '0')

if self.args:
args = ' ' + ' '.join([repr(arg) for arg in self.args])
else:
args = ''

return '{}#{} {} = {}'.format(
fullname, hex_id, ' '.join([str(arg) for arg in self.args]),
self.result)
return '{}{}{} = {}'.format(fullname, hex_id, args, self.result)

def infer_id(self):
representation = self.__repr__(ignore_id=True)

# Clean the representation
representation = representation\
.replace(':bytes ', ':string ')\
.replace('?bytes ', '?string ')\
.replace('<', ' ').replace('>', '')\
.replace('{', '').replace('}', '')

representation = re.sub(
r' \w+:flags\.\d+\?true',
r'',
representation
)
return crc32(representation.encode('ascii'))

def __str__(self):
fullname = ('{}.{}'.format(self.namespace, self.name)
Expand Down Expand Up @@ -214,3 +246,9 @@ def __str__(self):
return '{{{}:{}}}'.format(self.name, real_type)
else:
return '{}:{}'.format(self.name, real_type)

def __repr__(self):
# Get rid of our special type
return str(self)\
.replace(':date', ':int')\
.replace('?date', '?int')

0 comments on commit 79ee98a

Please sign in to comment.