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

[octetsream-codec] fix serialization and deserialization of nested objects #1262

Merged
merged 7 commits into from
Apr 5, 2024

Conversation

derwehr
Copy link
Contributor

@derwehr derwehr commented Apr 2, 2024

After using the octetstream codec's object serialization and deserialization for a while now, I discovered a bug when handling nested objects:

When serializing values, the object's bit-offset would not be passed on to the nested serialization call.

For example (added to the tests in this PR, too):
Serializing an object like

{
    "flags1": { "flag1": false, "flag2": true },
    "flags2": { "flag1": true, "flag2": false },
}

with the following DataSchema

{
    "type": "object",
    "properties": {
        "flags1": {
            "type": "object",
            "properties": {
                "flag1": { "type": "boolean", "ex:bitOffset": 3, "ex:bitLength": 1 },
                "flag2": { "type": "boolean", "ex:bitOffset": 4, "ex:bitLength": 1 },
            },
            "ex:bitLength": 8,
        },
        "flags2": {
            "type": "object",
            "properties": {
                "flag1": { "type": "boolean", "ex:bitOffset": 3, "ex:bitLength": 1 },
                "flag2": { "type": "boolean", "ex:bitOffset": 4, "ex:bitLength": 1 },
            },
            "ex:bitOffset": 8,
            "ex:bitLength": 8,
        },
    },
    "ex:bitLength": 16,
},
"application/octet-stream;length=2;"

I would expect: 0000 1000 0001 0000, i.e. Buffer[8, 16], but the current implementation returns Buffer[24, 0] because it does not pass ex:bitOffset of flags2 and therefore sets the bits of flags2 in the same byte as flags1 writing 0001 1000 0000 0000.


The issue when deserializing nested objects was that bytesToValue would only pass the bytes from offset to offset + length to objectToValue without adjusting the length parameter. Therefore, deserializing nested objects would throw an error:

Error: Lengths do not match, required: 2 provided: 1

I added a test case and a fix for this, too.

@derwehr derwehr changed the title [octetsream.codec] fix serialization and deserialization of nested objects [octetsream-codec] fix serialization and deserialization of nested objects Apr 2, 2024
Copy link

codecov bot commented Apr 2, 2024

Codecov Report

Attention: Patch coverage is 89.47368% with 8 lines in your changes are missing coverage. Please review.

Project coverage is 77.91%. Comparing base (ff32218) to head (1d86750).
Report is 10 commits behind head on master.

Files Patch % Lines
packages/core/src/codecs/octetstream-codec.ts 89.47% 6 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1262      +/-   ##
==========================================
+ Coverage   77.81%   77.91%   +0.10%     
==========================================
  Files          84       84              
  Lines       17523    17602      +79     
  Branches     1781     1810      +29     
==========================================
+ Hits        13635    13715      +80     
- Misses       3853     3854       +1     
+ Partials       35       33       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@danielpeintner danielpeintner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in general it is fine...

Please find below a suggested improvement

@@ -542,6 +543,7 @@ export default class OctetstreamCodec implements ContentCodec {
throw new Error("Missing 'length' parameter necessary for write");
}

const offset = schema["ex:bitOffset"] !== undefined ? parseInt(schema["ex:bitOffset"]) : 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to to a more sophisticated check.. not only for undefined but also NaN and/or invalid parameters?

Copy link
Contributor Author

@derwehr derwehr Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a check in the last commit.

The bytesToValue and valueTobytes functions could probably check most of the DataSchema values and the length parameter more thoroughly as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to introduce the checks it would be fine by me.. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some more checks (and tests making sure the checks work) in my last commit

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A "simpler" approach could have been a helper method that does the check (since I think the are almost all the same). Anyhow, fine like this as well 👍

Copy link
Member

@relu91 relu91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to go, thanks for adding tests too!

@relu91 relu91 merged commit 5a96838 into eclipse-thingweb:master Apr 5, 2024
12 checks passed
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

Successfully merging this pull request may close these issues.

3 participants