Skip to content

Add declarative syntax - #161

Merged
yunzheng merged 1 commit into
mainfrom
declarative
Nov 6, 2026
Merged

yunzheng merged 1 commit into
mainfrom
declarative

Conversation

@Schamper

@Schamper Schamper commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

This adds an optional declarative syntax for structure definitions, for when you want to write structures in a more Pythonic syntax.

>>> from dissect.cstruct.declarative import Struct, uint8, uint32, uint64
>>>
>>> class Header(Struct):
...     magic: uint8[4]
...     version: uint32
>>> class File(Struct):
...     header: Header  # structs can reference each other
...     size: uint64

Or to bring-your-own-cstruct:

>>> from dissect.cstruct import cstruct
>>> from dissect.cstruct.declarative import Struct
>>>
>>> cs = cstruct(endian=">")
>>>
>>> class Header(Struct, cs=cs):
...     magic: uint8[4]
...     version: uint32

The resulting classes are proper subclasses of Structure and have all the same behavior as regular cstruct structures.

@codecov

codecov Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 180 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.00%. Comparing base (9171926) to head (25ccff2).

Files with missing lines Patch % Lines
dissect/cstruct/declarative.py 0.00% 171 Missing ⚠️
dissect/cstruct/types/base.py 0.00% 7 Missing ⚠️
dissect/cstruct/types/structure.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff           @@
##            main    #161    +/-   ##
======================================
  Coverage   0.00%   0.00%            
======================================
  Files         23      24     +1     
  Lines       3658    3835   +177     
======================================
- Misses      3658    3835   +177     
Flag Coverage Δ
unittests 0.00% <0.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed

codspeed Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 45 untouched benchmarks
⏩ 47 skipped benchmarks1


Comparing declarative (25ccff2) with main (9171926)

Open in CodSpeed

Footnotes

  1. 47 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@codspeed

codspeed Bot commented Jul 9, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 14 untouched benchmarks


Comparing declarative (a47fcc4) with main (7678a8f)

Open in CodSpeed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds an optional “declarative” API for defining cstruct Structure/Union types using Python class syntax + type annotations, while keeping parity with existing cstruct behavior and allowing either auto-created or user-supplied cstruct instances.

Changes:

  • Introduces dissect.cstruct.declarative with Struct / Union bases, unbound type references (e.g. uint32, uint8[4]), pointer/array helpers, and field(...) specs (including typing.Annotated support).
  • Extends array subscripting (Type[...]) to accept string expressions (converted to Expression) for declarative string parsing.
  • Adds comprehensive tests for the declarative feature and updates Ruff per-file ignores for the new test module.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
dissect/cstruct/declarative.py New declarative structure/union definition layer built on annotations + metaclasses.
dissect/cstruct/types/base.py Allows __getitem__ array sizes to be provided as str expressions (parsed as Expression).
dissect/cstruct/__init__.py Exposes declarative Struct and field in the public package API.
tests/test_declarative.py Adds test coverage for declarative structs/unions, forward refs, pointers, arrays, Annotated, alignment, etc.
pyproject.toml Adds Ruff per-file ignores needed for declarative syntax test coverage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dissect/cstruct/declarative.py Resolved
Comment thread dissect/cstruct/declarative.py Resolved
@Schamper
Schamper force-pushed the declarative branch 5 times, most recently from 23a40d8 to d126209 Compare July 16, 2026 09:31

@Miauwkeru Miauwkeru left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some remarks when trying out to use this declarative version.
Currently the Struct instance will fail when you try to use dumps, print or initializing the structure.

Using the Header struct from the example, using it like this. it complains about the endianess of the attached cstruct instance, which doesn't exist.

E.g:

  • Header().dumps()
  • Header(b"heey0102")

Adding a cstruct instance in the class definition class Header(..., cs=cs): ... it cannot find the __fields__ attribute of the Struct.


Another thing I noticed is with an empty Struct instance, (e.g. Header()) where it creates an attribute error with the magic and version attributes.

Trying to print this Header instance will result into another error where it cannot find the fields attribute.

Comment thread dissect/cstruct/declarative.py Resolved
@Schamper
Schamper force-pushed the declarative branch 4 times, most recently from 2c9806f to cb04a63 Compare November 5, 2026 16:40
@Schamper
Schamper requested a review from yunzheng November 6, 2026 09:16
yunzheng
yunzheng previously approved these changes Nov 6, 2026

@yunzheng yunzheng left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Everything works beautifully from my end.

@yunzheng

yunzheng commented Nov 6, 2026

Copy link
Copy Markdown
Member

@Schamper can you also configure the endianness without cs=?

@Schamper

Schamper commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor Author

@Schamper can you also configure the endianness without cs=?

Not per structure (and it'd be difficult to add, since they use a shared cstruct instance, and endianness is configured per cstruct instance), but you can per read since #144:

Header(data, endian=">")

I added a description to the README since your ack.

@Schamper
Schamper requested a review from yunzheng November 6, 2026 10:46
@yunzheng

yunzheng commented Nov 6, 2026

Copy link
Copy Markdown
Member

@Schamper can you also configure the endianness without cs=?

Not per structure (and it'd be difficult to add, since they use a shared cstruct instance, and endianness is configured per cstruct instance), but you can per read since #144:

Header(data, endian=">")

I added a description to the README since your ack.

that makes sense, thanks

@yunzheng

yunzheng commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

thumbs up if you want this merged, or if you have any other changes, now is your time.

Love the docs btw. It's nice to read it so you don't have to go to the unit tests to see how it all works and how to use it.

@yunzheng
yunzheng merged commit 65eeecb into main Nov 6, 2026
24 checks passed
@yunzheng
yunzheng deleted the declarative branch November 6, 2026 11:00
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.

4 participants