-
-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make constraints explicitly constant and evaluated in compile time & move some computation there (OER/PER) #318
Conversation
Seems like that the previous constant evaluation problem applies only for default release builds, |
I think it's fine to have this optimisation, even if it's only for default release, because that is what most people use, since it's the default. |
macros/src/config.rs
Outdated
encoder.encode_extension_addition( | ||
#tag, | ||
<#ty as #crate_root::AsnType>::CONSTRAINTS.override_constraints(#constraints), | ||
<#ty as #crate_root::AsnType>::CONSTRAINTS.override_constraints(#constraint_name), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there's a benefit to making override_constraints
const and removing that evaluation from runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is quite hot function. I tried to make it const but there were some challenges related to Cow
type. Another hot function is
Lines 45 to 47 in 4e10e6b
pub fn value(&self) -> Option<Extensible<Value>> { | |
self.0.iter().find_map(|constraint| constraint.to_value()) | |
} |
which in theory could be also constant/pre-computed.
Would it be okay if I try change the constraints type to be #[derive(Debug, Clone)]
pub struct Constraints(pub &'static [Constraint]) I think there isn't any use case where it should not be possible to calculate the constraint in compile time? |
I don't think that will work with having types that wrap a constrained type and add another constraint. |
5505f02
to
f06e805
Compare
Could you explain why? I'm not sure I understand why you can't. |
Here is the relevant compiler error:
Generated code would look like: #[allow(clippy::mutable_key_type)]
impl<T: rasn::Encode> rasn::Encode for ContributedExtensionBlock<T>
where
T: ContributedExtension,
{
fn encode_with_tag_and_constraints<EN: rasn::Encoder>(
&self,
encoder: &mut EN,
tag: rasn::Tag,
constraints: rasn::types::Constraints,
) -> core::result::Result<(), EN::Error> {
#[allow(unused)]
let __rasn_field_id = &self.id;
#[allow(unused)]
let __rasn_field_extn = &self.extn;
encoder
.encode_sequence::<Self, _>(tag, |encoder| {
self.id.encode_with_tag(
encoder,
rasn::Tag::new(rasn::types::Class::Context, 0usize as u32),
)?;
const FIELD_CONSTRAINT_1: rasn::types::Constraints =
rasn::types::Constraints::from_fixed_size(
&<SequenceOf<T> as rasn::AsnType>::CONSTRAINTS.merge(
rasn::types::Constraints::new(&[rasn::types::Constraint::Size(
rasn::types::constraints::Extensible::new(
rasn::types::constraints::Size::new(
rasn::types::constraints::Bounded::start_from(
1i128 as usize,
),
),
)
.set_extensible(false),
)]),
),
);
self.extn.encode_with_tag_and_constraints(
encoder,
rasn::Tag::new(rasn::types::Class::Context, 1usize as u32),
FIELD_CONSTRAINT_1,
)?;
Ok(())
})
.map(drop)
}
} The issue is on part |
The above use-case is mainly related to use of information object classes and information object sets - however I checked the compiler crate and it does not use generics but rather just |
344c9a9
to
e856418
Compare
I'm hesitant to take away that functionality. I wonder if we could solve this by approaching it from a different way. What if the field constraints constants were specified in the I made a small prototype to test if it could resolve the constants, and it seems like it works. |
e856418
to
c58dbaf
Compare
59eb798
to
a2fa9e6
Compare
I don't think that completely explicit constant constraints are possible after all. ASN.1 standard allows newtyping the type up to infinity and each new type can introduce additional constraints. There is a bunch of set theory how to calculate the final constraints. This isn't currently properly noted in all scenarios and I also did not note it so I was able to make it constant (excluding the generics). I think I will just improve the situation slightly on this PR and I cannot solve it completely for now. |
a2fa9e6
to
e687581
Compare
e687581
to
2f577fc
Compare
Thank you for your PR! |
Would you mind making the issue for this? |
Small performance improvement again.
Seems like the compiler does not currently evaluate constant constraints in compile-time.
It helps if we move the constraint construction to separate expression like follows
OER/BER gets performance boost immediately, but PER decoding gets regression. Need to investigate that still.