Skip to content

Instantly share code, notes, and snippets.

@phire
Created April 3, 2024 12:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phire/490965370c46caac5a6b0df5bd2147f3 to your computer and use it in GitHub Desktop.
Save phire/490965370c46caac5a6b0df5bd2147f3 to your computer and use it in GitHub Desktop.
from construct import *
def sizeof_struct(subcon, value, parent=None):
ctx = Container(value)
ctx._ = parent or Container()
ctx._params = Container()
ctx._parsing = False
ctx._sizing = True
ctx._building = False
size = 0
for sc in subcon.subcons:
if sc.name:
size += sizeof(sc.subcon, ctx[sc.name], parent=ctx)
else:
size += sc._sizeof(ctx, "(sizeof)")
return size
def sizeof(subcon, value, parent=None):
if not parent or not hasattr(parent, "_params"):
parent = Container(parent) if parent else Container()
parent._params = Container()
parent._parsing = False
parent._sizing = True
parent._building = False
try:
return subcon._sizeof(parent, "(sizeof)")
except SizeofError:
pass
if isinstance(subcon, (Hex, Dec, HexDump, Aligned, StringEncoded, OffsettedEnd)):
return sizeof(subcon.subcon, value, parent)
if isinstance(subcon, (GreedyRange, RepeatUntil)):
subcon = subcon.subcon
itemsize = subcon.sizeof()
if itemsize:
return len(value) * itemsize
elif value and hasattr(value[name][0], "sizeof"):
return sum([x.sizeof() for x in value])
else:
return sum([sizeof(subcon, x, parent) for x in value])
if subcon == GreedyBytes:
return len(value)
if isinstance(subcon, Prefixed):
return subcon.lengthfield.sizeof() + len(value)
if isinstance(subcon, NullTerminated):
return sizeof(subcon.subcon, value, parent) + 1
if isinstance(subcon, Struct):
return sizeof_struct(subcon, value, parent)
raise Exception(f"Don't know how to calculate size for {subcon}, {value}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment