4

This post is about Python's Construct library

THE CODE

These are the definitions of my constructs:

from construct import *

AttributeHandleValuePair = "attribute_handle_value_pair" / Struct(
    "handle" / Int16ul,
    "value" / Bytes(this._.length - 2)
)

AttReadByTypeResponse = "read_by_type_response" / Struct(
    "length" / Int8ul,  # The size in bytes of each handle/value pair
    "attribute_data_list" / AttributeHandleValuePair[2]
)

THE PROBLEM

Trying to run the following command:

AttReadByTypeResponse.sizeof(dict(length=4, attribute_data_list=[dict(handle=1, value=2), dict(handle=3, value=4)])

I receive the following error:

SizeofError: cannot calculate size, key not found in context
    sizeof -> read_by_type_response -> attribute_data_list -> attribute_handle_value_pair -> value

WHAT I FOUND OUT

The size of the value field for each attribute_handle_value_pair is derived from the length field of its parent. I think that the sizeof() method is trying to calculate the size of attribute_handle_value_pair first, while the length field of read_by_type_response is still undefined, therefore it cannot calculate its size.

I tried changing the the length of the value field to a static value and it worked well.

MY QUESTION

How can I calculate the sizeof() for a construct that is depending of its parent construct?

Should I redesign the way this protocol is modeled? If so then how?

Dan Shemesh
  • 464
  • 3
  • 13
  • 1
    looks like an issue of circular dependency rather than a parent/ child evaluation. the docs *do* note that cases like that where the construct uses an array of variable size might trigger `SizeofError` - http://construct.readthedocs.io/en/latest/basics.html#variable-length-fields – Uriel Jun 25 '17 at 14:50
  • I am the Construct developer. There is no circular dependency. This could should work fine. – ArekBulski Mar 21 '18 at 17:56
  • d = Struct( "length" / Int8ub, "data" / Bytes(this.length), ) d.sizeof() construct.core.SizeofError: cannot calculate size, key not found in context Can you please share the code snippet , which fixed SizeofError – RajaniKanth Reddy Dec 11 '18 at 17:20

1 Answers1

2

This is currently still an issue in Construct 2.9/2.10 (2.8 appears to be fine).

As a workaround, you can compute the size with a given context by summing the size of the subcons and passing in the length directly.

sum(sc.sizeof(length=4) for sc in AttReadByTypeResponse.subcons)

If you use the new compiled struct feature, you will need to access the original struct using defersubcon.

compiled_struct = AttReadByTypeResponse.compile()    
sum(sc.sizeof(length=4) for sc in compiled_struct.defersubcon.subcons)
Dominic A.
  • 103
  • 4
Dominic A.
  • 31
  • 2