Skip to content

Conversation

@tarcieri
Copy link
Member

Previously der lacked an abstraction for automatically setting up nested readers when decoding values, so every DecodeValue impl ended up handling its own nesting.

This adds a new provided method to the Reader trait which automatically handles nesting.

This change is backwards compatible in that if a DecodeValue impl does its own reader.read_nested, it will just create another nested reader of the same length, which is redundant but doesn't break anything. However, we should remove all of the read_nested calls from DecodeValue impls with this approach anyway as they're redundant.

Using a provided method for this opens up the possibility of reader-specific handling of field decoding, which would be useful for addressing indefinite length handling for BER decoding (#779).

@tarcieri tarcieri requested a review from baloo June 20, 2025 19:50
@tarcieri
Copy link
Member Author

cc @dishmaker

Previously `der` lacked an abstraction for automatically setting up
nested readers when decoding values, so every `DecodeValue` impl ended
up handling its own nesting.

This adds a new provided method to the `Reader` trait which
automatically handles nesting.

This change is backwards compatible in that if a `DecodeValue` impl does
its own `reader.read_nested`, it will just create another nested reader
of the same length, which is redundant but doesn't break anything.
However, we should remove all of the `read_nested` calls from
`DecodeValue` impls with this approach anyway as they're redundant.

Using a provided method for this opens up the possibility of
reader-specific handling of field decoding, which would be useful for
addressing indefinite length handling for BER decoding (#779).
@tarcieri tarcieri force-pushed the der/reader-read-value branch from 8f8f382 to 6d54f21 Compare June 20, 2025 19:52
@tarcieri
Copy link
Member Author

Note: this pretty much eliminates any direct calls to read_nested, although I see there are a few lingering places it's used (e.g. ecdsa)

@tarcieri tarcieri merged commit 2e80d58 into master Jun 20, 2025
107 checks passed
@tarcieri tarcieri deleted the der/reader-read-value branch June 20, 2025 20:32
@dishmaker
Copy link
Contributor

Looks good. Removes boilerplate 👍

Maybe I will add negative tests for bad nesting (i.e. when read_nested should fail).

@tarcieri
Copy link
Member Author

@dishmaker more testing around failure cases in nested message handling would be greatly appreciated

tarcieri added a commit that referenced this pull request Jun 21, 2025
This was added in #1877 but the real value of that PR was the automatic
`read_nested` on `DecodeValue` impls. `Reader::read_value` isn't
actually necessary for that at all.

It may be useful in the future if we introduce a BER reader that can
handle decoding constructed e.g. strings from indefinite length
encoding, but since we don't actually have anything like that yet,
removing this avoids some unnecessary duplication and API surface for
the `Reader`.
tarcieri added a commit that referenced this pull request Jun 21, 2025
This was added in #1877 but the real value of that PR was the automatic
`read_nested` on `DecodeValue` impls. `Reader::read_value` isn't
actually necessary for that at all.

It may be useful in the future if we introduce a BER reader that can
handle decoding constructed e.g. strings from indefinite length
encoding, but since we don't actually have anything like that yet,
removing this avoids some unnecessary duplication and API surface for
the `Reader`.
tarcieri added a commit that referenced this pull request Jul 2, 2025
One of the blockers for addressing indefinite length handling (#779) has
been where to consume the EOC tag.

This commit (re)introduces `Reader::read_value` (added in #1877, removed
in #1887) and handles decoding the EOC there. This gives us a single
place where EOC can be handled for all constructed messages.

With these changes, the decoder is able to parse `cms_ber.bin` from
`cms/tests`, from which the `cms_der.bin` file has been translated. This
file provides a real-world example of nested indefinite lengths from
CMS.

Note, however, that the example contains a constructed `Any` which isn't
yet being correctly handled. A `TODO` for ensuring the BER and DER
decode identically has been added.
tarcieri added a commit that referenced this pull request Jul 2, 2025
One of the blockers for addressing indefinite length handling (#779) has
been where to consume the EOC tag.

This commit (re)introduces `Reader::read_value` (added in #1877, removed
in #1887) and handles decoding the EOC there. This gives us a single
place where EOC can be handled for all constructed messages.

With these changes, the decoder is able to parse `cms_ber.bin` from
`cms/tests`, from which the `cms_der.bin` file has been translated. This
file provides a real-world example of nested indefinite lengths from
CMS.

Note, however, that the example contains a constructed `Any` which isn't
yet being correctly handled. A `TODO` for ensuring the BER and DER
decode identically has been added.
tarcieri added a commit that referenced this pull request Jul 2, 2025
One of the blockers for addressing indefinite length handling (#779) has
been where to consume the EOC tag.

This commit (re)introduces `Reader::read_value` (added in #1877, removed
in #1887) and handles decoding the EOC there. This gives us a single
place where EOC can be handled for all constructed messages.

With these changes, the decoder is able to parse `cms_ber.bin` from
`cms/tests`, from which the `cms_der.bin` file has been translated. This
file provides a real-world example of nested indefinite lengths from
CMS.

Note, however, that the example contains a constructed `Any` which isn't
yet being correctly handled. A `TODO` for ensuring the BER and DER
decode identically has been added.
tarcieri added a commit that referenced this pull request Jul 2, 2025
One of the blockers for addressing indefinite length handling (#779) has
been where to consume the EOC tag.

This commit (re)introduces `Reader::read_value` (added in #1877, removed
in #1887) and handles decoding the EOC there. This gives us a single
place where EOC can be handled for all constructed messages.

With these changes, the decoder is able to parse `cms_ber.bin` from
`cms/tests`, from which the `cms_der.bin` file has been translated. This
file provides a real-world example of nested indefinite lengths from
CMS.

Note, however, that the example contains a constructed `Any` which isn't
yet being correctly handled. A `TODO` for ensuring the BER and DER
decode identically has been added.
tarcieri added a commit that referenced this pull request Jul 2, 2025
One of the blockers for addressing indefinite length handling (#779) has
been where to consume the EOC tag.

This commit (re)introduces `Reader::read_value` (added in #1877, removed
in #1887) and handles decoding the EOC there. This gives us a single
place where EOC can be handled for all constructed messages.

With these changes, the decoder is able to parse `cms_ber.bin` from
`cms/tests`, from which the `cms_der.bin` file has been translated. This
file provides a real-world example of nested indefinite lengths from
CMS.

Note, however, that the example contains a constructed `Any` which isn't
yet being correctly handled. A `TODO` for ensuring the BER and DER
decode identically has been added.
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