Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DispatchTarget does not support FieldArray #48

Open
martinpelikan opened this issue Mar 15, 2017 · 1 comment
Open

DispatchTarget does not support FieldArray #48

martinpelikan opened this issue Mar 15, 2017 · 1 comment

Comments

@martinpelikan
Copy link

martinpelikan commented Mar 15, 2017

Among other things, the protocol I'm working with includes a type and length in its metadata. The payload is a list of substructures that will be of the type specified. Here's a stripped down version of what I'm talking about.

class BinaryProtocol(Structure):
    # METADATA
    a = UBInt32()
    b = SBInt16()
    c = DispatchField(SBInt8())
    e = LengthField(SBInt16())

    # DATA
    data = DispatchTarget(None, c, {
        3: FieldArray(TypeThreeStruct),
        4: FieldArray(TypeFourStruct),
    })

It looks like the current implementation does not allow you to combine these two behaviours, you can either have a non-variable structure repeated, or a single structure of a variable type. The error raised when attempting the above is shown below:

/home/mpelikan/.local/lib/python3.6/site-packages/suitcase/structure.py in unpack(self, data, trailing)
    339 
    340     def unpack(self, data, trailing=False):
--> 341         return self._packer.unpack(data, trailing)
    342 
    343     def pack(self):

/home/mpelikan/.local/lib/python3.6/site-packages/suitcase/structure.py in unpack(self, data, trailing)
     62     def unpack(self, data, trailing=False):
     63         stream = BytesIO(data)
---> 64         self.unpack_stream(stream)
     65         stream.tell()
     66         if trailing:

/home/mpelikan/.local/lib/python3.6/site-packages/suitcase/structure.py in unpack_stream(self, stream)
    162 
    163             greedy_data_chunk = inverted_stream.read()[::-1]
--> 164             greedy_field.unpack(greedy_data_chunk)
    165 
    166         if crc_fields:

/home/mpelikan/.local/lib/python3.6/site-packages/suitcase/fields.py in unpack(self, data, **kwargs)
    404             raise SuitcaseParseError("Input data contains type byte not"
    405                                      " contained in mapping")
--> 406         message_instance = target_msg_type()
    407         self.setval(message_instance)
    408         self._value.unpack(data)

TypeError: 'FieldPlaceholder' object is not callable
@martinpelikan
Copy link
Author

martinpelikan commented Mar 16, 2017

Looks like one workaround is to wrap the FieldArray in a Structure, then use that as the DispatchTarget. This comes at the cost of an additional .subfield access. Using the example above:

class TypeThreeStruct(Structure):
    data = FieldArray(ActualTypeThreeStruct)

class BinaryProtocol(Structure):
    # METADATA
    a = UBInt32()
    b = SBInt16()
    c = DispatchField(SBInt8())
    e = LengthField(SBInt16())

    # DATA
    data = DispatchTarget(None, c, {
        3: TypeThreeStruct,
    })

Then you could do:

thing = BinaryProtocol()
thing.unpack(b'...')
thing.data.data[index_of_interest]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant