Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

der: add IsConstructed trait, impl'ed on any FixedTag #1744

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dishmaker
Copy link
Contributor

@dishmaker dishmaker commented Mar 27, 2025

Closes #1741

This PR drops the need to implement Tagged on all structs that are IMPLICIT.

For example CHOICE does not implement FixedTag, but is always constructed.

@tarcieri
Copy link
Member

This doesn't seem to do a whole lot as-is. What else are you planning on impl'ing IsConstructed on?

@dishmaker
Copy link
Contributor Author

On trait Choice and my weird little edge case where derive(Choice) needed Tagged on something that wasn't.

@dishmaker
Copy link
Contributor Author

dishmaker commented Mar 27, 2025

If I remember correctly, the edge case is here:
https://github.com/monai/node-passport/blob/master/lib/pkcs15/cryptographic_information_framework.asn1#L181

So it's a CHOICE with [0] CHOICE inside for ObjectValue {RSAPublicKeyChoice}

@tarcieri
Copy link
Member

You should try to add it there, as I think for what you’re proposing the blanket impls(?) would conflict

@dishmaker dishmaker marked this pull request as draft March 27, 2025 15:27
@dishmaker
Copy link
Contributor Author

It will take me some time to recreate the Tagged IMPLICIT bug with CHOICE inside [0] CHOICE :)

@dishmaker
Copy link
Contributor Author

dishmaker commented Mar 28, 2025

I give up. It's pretty much impossible to implement this case in current der, without splitting EXPLICIT and IMPLICIT encoders.

#[derive(Choice)]
pub enum ObjectValue<T>
where
    for<'a> T: /* what to put here ? */,
{
    Indirect(Path),

    #[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
    Direct(T),
}
[Spoiler] error[E0277]
error[E0277]: the trait bound `RSAPublicKeyChoice: FixedTag` is not satisfied
   --> der/tests/derive.rs:261:52
    |
261 |             let object_value = ObjectValue::Direct(rsa_choice);
    |                                ------------------- ^^^^^^^^^^ the trait `der::Sequence<'_>` is not implemented for `RSAPublicKeyChoice`
    |                                |
    |                                required by a bound introduced by this call
    |
    = note: required for `RSAPublicKeyChoice` to implement `FixedTag`
note: required by a bound in `ObjectValue::Direct`
   --> der/tests/derive.rs:220:78
    |
220 |             for<'a> T: Encode + Decode<'a> + EncodeValue + DecodeValue<'a> + FixedTag,
    |                                                                              ^^^^^^^^ required by this bound in `ObjectValue::Direct`
...
225 |             Direct(T),
    |             ------ required by a bound in this tuple variant

So ObjectValue::Direct should be bound:

  • only by EncodeValue + DecodeValue<'a> + IsConstructed,
  • but now Encode + Decode<'a> + EncodeValue + DecodeValue<'a> + FixedTag is required.

Tagged and FixedTag traits are forced elsewere in the crate by ContextSpecific wrapper.

@dishmaker
Copy link
Contributor Author

Btw CHOICE inside CHOICE isn't a problem. Such case can be simplified by hand.

/// ```asn1
/// ReferencedValue {Type} ::= CHOICE {
///     path Path,
///     url URL
/// }
/// URL ::= CHOICE {
///     url CHOICE {
///         printable PrintableString, 
///         ia5 IA5String
///     },
///     urlWithDigest [3] SEQUENCE {
///         url IA5String,
///         digest DigestInfoWithDefault
///     }
/// }
/// ```
#[derive(Choice, Clone, Debug, Eq, PartialEq)]
#[tag_mode = "IMPLICIT"]
pub enum ReferencedValue {
    Path(Path),
    PrintableStringUrl(PrintableString),
    Ia5StringUrl(Ia5String),
    #[asn1(context_specific = "3")]
    UrlWithDigest(()),
}

der_derive: impl IsConstructed on derive(Choice)

der: draft of test for IsConstructed vs Tagged edge case

der: test: generic CHOICE inside [0] IMPLICIT CHOICE

Revert "der: test: generic CHOICE inside [0] IMPLICIT CHOICE"

This reverts commit dda1215.

Revert "der: draft of test for IsConstructed vs Tagged edge case"

This reverts commit 5daa9ba.

der: add IsConstructed test

docs
@dishmaker dishmaker force-pushed the dishmaker/der_isconstructed_trait branch from dda1215 to 5ee5ef6 Compare April 3, 2025 14:25
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

der: add IsConstructed trait
2 participants