Skip to content

Alternative way of variable length bytes field. #3

Description

@robots

Hi,

This is not issue, this is more of "documenting" of features for future users.

I needed something that is like "vartext" but with bytes. The example shown in README.md didn't work well.

So i implemented varbytes field.

def varbytes(
    length: Value[int],
    *,
    default: bytes = ...
):
    class Bytes(Adapter):
        def encode(self, value: bytes, ctx: Context) -> bytes:
            return value

        def decode(self, value: bytes, ctx: Context) -> bytes:
            return value

    return adapter(Bytes())(
        field(
            lambda ctx: (
                len(ctx.P.self) if ctx.G.packing else evaluate(ctx, length)
            ),
            default=default,
        )
    )

This is strongly inspired by vartext, but simplified as it only supports variable length. (Yes encode and decode could be lambdas, meh)

@dataclass
@datastruct(endianness=Endianness.LITTLE, padding_pattern=b"\x00")
class Packet1(DataStruct):
    list: int = field('B')
    num: int = field('H')
    count: int = field('H')
    data: bytes = varbytes(lambda ctx: ctx.G.root.length-5)

@dataclass
@datastruct(endianness=Endianness.LITTLE, padding_pattern=b"\x00")
class Packet(DataStruct):
    length: int = built("B", lambda ctx: ctx.body.sizeof())
    body: Any = switch(lambda ctx: ctx.typ)(
            PACKET1 = (Packet1, subfield()),
        )

When packing Packet.length is automatically calculated from length of data in Packet1 (or any other body packet)
When unpacking Packet1.data length is calculated from Packet.length - 5 (which is length of B+H+H))

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions