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

[Feature] Construct build to return also parse #1059

Open
alonbl opened this issue Dec 22, 2023 · 0 comments
Open

[Feature] Construct build to return also parse #1059

alonbl opened this issue Dec 22, 2023 · 0 comments

Comments

@alonbl
Copy link

alonbl commented Dec 22, 2023

Hello,

When building input is dict (context) and the output is bytes.
When parsing the input is byte and the output is the construct instance.

The construct implementation does a lot of work in order to parse the data and prepare the construct instance.

The implementation is asymmetric the context lacks much of the construct logic and its notation is different, in this example I show the basic sequence matching between request and response, as I dig more into the parsing feature there are many more examples that I can provide.

import construct

REQUEST_STRUCT = construct.Struct("sequence" / construct.Int32ul, "a" / construct.Int32ul)
RESPONSE_STRUCT = construct.Struct("sequence" / construct.Int32ul, "a" / construct.Int32ul)

request_context = {"sequence": 0x1234, "a": 5}
request_raw = REQUEST_STRUCT.build(request_context)
response_raw = bytes((0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))
response_struct = RESPONSE_STRUCT .parse(response_raw)
if request_context["sequence"] == response_struct.sequence: print("OK")

The workaround I use is to build/parse the request, this enables symmetric processing, for example:

import construct

REQUEST_STRUCT = construct.Struct("sequence" / construct.Int32ul, "a" / construct.Int32ul)
RESPONSE_STRUCT = construct.Struct("sequence" / construct.Int32ul, "a" / construct.Int32ul)

request_context = {"sequence": 0x1234, "a": 5}
request_raw = REQUEST_STRUCT.build(request_context)
request_struct = REQUEST_STRUCT.parse(request_raw )                       # added
response_raw = bytes((0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))
response_struct = RESPONSE_STRUCT .parse(response_raw)
if request_struct .sequence == response_struct.sequence: print("OK")      # modified

I would like to believe that while building the raw bytes out of context and construct classes, construct also builds the hierarchy of instances so that it may be returned to the user as output so that the extra parse will not be required when processing the classes.

I though of something like adding build_with_struct() which returns a tuple with both the raw bytes and the constructed classes, for example:

import construct

REQUEST_STRUCT = construct.Struct("sequence" / construct.Int32ul, "a" / construct.Int32ul)
RESPONSE_STRUCT = construct.Struct("sequence" / construct.Int32ul, "a" / construct.Int32ul)

request_context = {"sequence": 0x1234, "a": 5}
request_raw,  request_struct = REQUEST_STRUCT.build_with_struct(request_context)
response_raw = bytes((0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))
response_struct = RESPONSE_STRUCT .parse(response_raw)
if request_struct .sequence == response_struct.sequence: print("OK") 

Thanks,

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

No branches or pull requests

2 participants