Browse Source

added StructReader

pull/55/head
Rossen Georgiev 9 years ago
parent
commit
513c68ca08
  1. 6
      docs/api/steam.util.rst
  2. 39
      steam/core/msg/structs.py
  3. 44
      steam/util/binary.py

6
docs/api/steam.util.rst

@ -22,4 +22,10 @@ util.web
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:
util.binary
-----------
.. automodule:: steam.util.binary
:members:
:undoc-members:
:show-inheritance:

39
steam/core/msg/structs.py

@ -1,8 +1,10 @@
"""Classes to (de)serialize various struct messages""" """Classes to (de)serialize various struct messages"""
import struct import struct
import six import six
from six.moves import range
from steam.enums import EResult, EUniverse from steam.enums import EResult, EUniverse
from steam.enums.emsg import EMsg from steam.enums.emsg import EMsg
from steam.util.binary import StructReader
_emsg_map = {} _emsg_map = {}
@ -136,19 +138,18 @@ class ClientVACBanStatus(StructMessage):
StructMessage.__init__(self, data) StructMessage.__init__(self, data)
def load(self, data): def load(self, data):
numBans, = struct.unpack_from("<I", data) buf = StructReader(data)
offset = 4 numBans, = buf.read_format("<I")
for _ in six.moves.range(numBans): for _ in range(numBans):
m = self.VACBanRange() m = self.VACBanRange()
m.start, m.end, _ = struct.unpack_from("<III", data, offset)
self.ranges.append(m) self.ranges.append(m)
m.start, m.end, _ = buf.read_format("<III")
if m.start > m.end: if m.start > m.end:
m.start, m.end = m.end, m.start m.start, m.end = m.end, m.start
offset += 4 + 4 + 4
def __str__(self): def __str__(self):
text = ["numBans: %d" % self.numBans] text = ["numBans: %d" % self.numBans]
@ -179,12 +180,9 @@ class ClientChatMsg(StructMessage):
return rbytes return rbytes
def load(self, data): def load(self, data):
(self.steamIdChatter, buf = StructReader(data)
self.steamIdChatRoom, self.steamIdChatter, self.steamIdChatRoom, self.ChatMsgType = buf.read_format("<QQI")
self.ChatMsgType, self.text = buf.read_cstring().decode('utf-8')
) = struct.unpack_from("<QQI", data)
self.text = data[struct.calcsize("<QQI"):-1].decode('utf-8')
def __str__(self): def __str__(self):
return '\n'.join(["steamIdChatter: %d" % self.steamIdChatter, return '\n'.join(["steamIdChatter: %d" % self.steamIdChatter,
@ -254,7 +252,7 @@ class ClientMarketingMessageUpdate2(StructMessage):
def __str__(self): def __str__(self):
return '\n'.join(["{", return '\n'.join(["{",
"id: %s" % self.id, "id: %s" % self.id,
"url: %s" % self.url, "url: %s" % repr(self.url),
"flags: %d" % self.flags, "flags: %d" % self.flags,
"}", "}",
]) ])
@ -270,19 +268,16 @@ class ClientMarketingMessageUpdate2(StructMessage):
StructMessage.__init__(self, data) StructMessage.__init__(self, data)
def load(self, data): def load(self, data):
self.time, count = struct.unpack_from("<II", data) buf = StructReader(data)
offset = 4 + 4 self.time, count = buf.read_format("<II")
for _ in six.moves.range(count):
length, = struct.unpack_from("<I", data, offset)
url_length = length-4-8-4
offset += 4
for _ in range(count):
m = self.MarketingMessage() m = self.MarketingMessage()
m.id, m.url, _, m.flags = struct.unpack_from("<Q%dssI" % (url_length - 1), data, offset)
self.messages.append(m) self.messages.append(m)
offset += 8 + url_length + 4 length, m.id = buf.read_format("<IQ")
m.url = buf.read_cstring().decode('utf-8')
m.flags = buf.read_format("<I")
def __str__(self): def __str__(self):
text = ["time: %s" % self.time, text = ["time: %s" % self.time,

44
steam/util/binary.py

@ -0,0 +1,44 @@
import struct
class StructReader(object):
def __init__(self, data):
"""Simplifies parsing of struct data from bytes
:param data: data bytes
:type data: :class:`bytes`
"""
if not isinstance(data, bytes):
raise ValueError("Requires bytes")
self.data = data
self.offset = 0
def read_cstring(self):
"""Reads a single null termianted string
:return: string without bytes
:rtype: :class:`bytes`
"""
null_index = self.data.find(b'\x00', self.offset)
text = self.data[self.offset:null_index] # bytes without the null
self.offset = null_index + 1 # advanced past null
return text
def read_format(self, format_text):
"""Unpack bytes using struct modules format
:param format_text: struct's module format
:type format_text: :class:`str`
:return data: result from :func:`struct.unpack_from`
:rtype: :class:`tuple`
"""
data = struct.unpack_from(format_text, self.data, self.offset)
self.offset += struct.calcsize(format_text)
return data
def skip(self, n):
"""Skips the next ``n`` bytes
:param n: number of bytes to skip
:type n: :class:`int`
"""
self.offset += n
Loading…
Cancel
Save