Skip to content

Custom context can't be passed alongside with Endian and Limit #537

@eirnym

Description

@eirnym

More information can be found in discussion #536

How to reproduce:

  1. Implement custom reader for custom format using DekuReader with Vec<u8> inside, but requiring limit
  2. Add custom context value, such as u8 in front of other context values (as shown in Vec<T> implementation.
  3. From TargetModel pass tripple to satisfy all 3 context parts
  4. Check calls from TargetModel to model implemented above using cargo-expand.

it will show call from_reader_with_ctx if only Endian has been specified:

                    let __deku_value = <CustomModel as ::deku::DekuReader<
                        '_,
                        _,
                    >>::from_reader_with_ctx(
                        __deku_reader,
                        (
                            ::deku::ctx::Endian::Little,
                            (1u8, Limit::from(10), Endian::Little),
                        ),
                    )?;

or Limit and Endian if both has been specified

               let __deku_value = <CustomModel as ::deku::DekuReader<
                            '_,
                            _,
                        >>::from_reader_with_ctx(
                            __deku_reader,
                            (
                                ::deku::ctx::Limit::new_count(
                                    usize::try_from(*((10).borrow()))?,
                                ),
                                (
                                    ::deku::ctx::Endian::Little,
                                    (1u8, Limit::from(10), Endian::Little),
                                ),
                            ),
                        )?

Thus only (Limit<u8, Predicate>, (Endian, u8)) quite strange tuple can be used instead of (Limit<u8, Predicate>, Endian, u8) or even (u8, Limit<u8, Predicate>, Endian, u8), which is an expected result.

I don't even remind that context for reading and writing may be different as we can see in reference implementations.

Taking in account information above, I have following recommendations to improve code generation:

  1. Change tuple (Limit<u8, Predicate>, (Endian, CustomContext)) to something more readable like (Limit<u8, Predicate>, Endian, u8) or (u8, Limit<u8, Predicate>, Endian)
  2. Add ctx_read and ctx_write for different custom contexts for reading and writing. e.g in example in the discussison, compression level is only used for writing.
  3. Detect in macro (if possible) if reader and writer require endianess and limit. E.g. limit is useless for writing, but useful for reading, but field could be fixed length.

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