Skip to content

Support casting to a KnownLayout type with a user-provided length computed dynamically #1289

@joshlf

Description

@joshlf

See also: #1290, #1328, #5 (comment)

Requirements

  • Length field that encodes the number of elements
  • Length field that encodes the number of bytes (where each element might be multiple bytes long)
  • Length field that encodes the number of bytes of a fixed-size header plus a variable number of elements (e.g. IPv4 total length field)
  • Length field that should be interpreted as a number of quanta, but these quanta are not equal to the number of trailing elements (e.g. IPv4 IHL field)
  • Length field that encodes the length of multiple variable-length sections simultaneously. The element sizes of each section may be different, but the number of elements in each section is the same. (See Discord discussion for context.)
  • Must play nicely with packet::BufferView::take_front and friends

Details

Some formats have an explicit length field, and some use cases with these formats require parsing a subset of the available bytes based on that length field. We'd like to write something like:

#[derive(KnownLayout, FromBytes)]
#[repr(C)]
struct UdpHeader {
    src_port: [u8; 2],
    dst_port: [u8; 2],
    length: [u8; 2],
    checksum: [u8; 2],
}

#[derive(KnownLayout, FromBytes)]
struct UdpPacket {
    header: UdpHeader,
    body: [u8],
}

Unfortunately, all of the conversions we permit today require the number of bytes to be parsed to be known ahead of time - either it's simply the entire source byte slice, or it's computed from a fixed number of trailing slice elements.

Ideally, we could support an API that permits the caller to specify how to extract the length and then use that to determine the number of bytes to parse.

One idea: Do one parsing pass, then allow the user to provide a callback which extracts the length field. Finally, re-parse using the extracted length. There may be multiple axes we need to consider:

  • What is the type of the length field? Can we just require this callback to return a usize, or do we need to support other numeric types?
  • Will the length field always describe the byte length of the trailing field? What if it's a count of elements that are larger than 1 byte in size each? What if it instead describes the overall length of the packet, including the header?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions