-
Notifications
You must be signed in to change notification settings - Fork 14
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 Oid::from a const fn #20
Comments
I think you are right. Since While rusticata/der-parser#17 would allow a const fn, it needs the DER encoded format. So instead of The const OID_RSA_ENCRYPTION: Oid = oid!(1.2.840.113549.1.1.1);
const OID_EC_PUBLIC_KEY: Oid = oid!(1.2.840.10045.2.1);
fn foo(oid: Oid) {
match oid {
OID_RSA_ENCRYPTION => { .. },
OID_EC_PUBLIC_KEY => { .. },
}
} See dtolnay/proc-macro-hack#20 and rust-lang/rust#54727 for the issues related to using the macro in pattern position directly. On nightly a proc macro could be used in pattern position with the |
A solution without rusticata/der-parser#17 would be to expose the field of the impl Oid {
fn identifiers(&self) -> &[u64] { &self.0 }
} you could match like this: const OID_RSA_ENCRYPTION: &[u64] = &[1, 2, 840, 113549, 1, 1, 1];
const OID_EC_PUBLIC_KEY: &[u64] = &[1, 2, 840, 10045, 2, 1];
fn foo(oid: Oid) {
match oid.identifiers() {
OID_RSA_ENCRYPTION => { .. },
OID_EC_PUBLIC_KEY => { .. },
}
} |
After merging rusticata/der-parser#18, things have changed since assert_eq!(oid, oid!(1.2.840.113549.1.1.1)); However, as explained, this cannot be used yet with global items because the construction of an There is a workaround converting to string, but I find it not elegant: const OID_RSA_ENCRYPTION: &str = "1.2.840.113549.1.1.1";
fn compare_oid(oid: &Oid) -> bool {
match oid.to_id_string().as_ref() {
OID_RSA_ENCRYPTION => true,
_ => false,
}
} Finally, the third solution, that I used for lazy_static! {
static ref OID_REGISTRY: HashMap<Oid<'static>, OidEntry> = {
let mut m = HashMap::new();
m.insert(Oid::from(&[0]).unwrap(), OidEntry{sn:"UNDEF", ln:"undefined", nid:Nid::Undef});
// ...
m
};
}
pub fn oid2nid(oid: &Oid) -> Result<Nid, NidError> {
OID_REGISTRY
.get(oid)
.map(|ref o| o.nid)
.ok_or(NidError)
} Again, having a static/const declaration would be nice. @jannschu , any thoughts? |
@str4d: I played a bit with this. I suggest the following code with the new api: use der_parser::oid;
const OID_RSA_ENCRYPTION: &[u8] = &oid!(raw 1.2.840.113549.1.1.1);
const OID_EC_PUBLIC_KEY: &[u8] = &oid!(raw 1.2.840.10045.2.1);
fn foo(oid: &Oid) {
match oid.bytes() {
OID_RSA_ENCRYPTION => { ... },
OID_EC_PUBLIC_KEY => { ... },
...
}
} This is as static as it gets, I guess. No strings, no allocation. At compile time the constants will become the DER encoded oid. The match then compares the encoded forms. You might want to add a check for a relative oid ( I also discovered that using constants in patterns is still restricted (see rust-lang/rust#31434 for progress). The ideal api would allow match some_oid {
oid!(...) => {...},
...
} But that is currently not achievable I think (you can use @chifflier: The code in |
Maybe I should expand the |
Even cleaner solution: Make struct OidEntry {
sn: &'static str,
ln: &'static str,
nid: Nid,
oid: Oid<'static>,
}
const OID_REGISTRY : &[OidEntry] = &[
OidEntry{ sn:"UNDEF", ln:"undefined", nid:Nid::Undef, oid: oid!(0) },
...
];
fn nid2sn(nid: Nid) -> Result<&'static str, NidError> {
OID_REGISTRY
.iter()
.find(|ref o| o.nid == nid)
.map(|ref o| o.sn)
.ok_or(NidError)
} I will create a pull request (and also add more documentation for Oid and the macro). |
Great, thanks @jannschu ! |
It seems Rust 1.45 now supports proc macros in expression and pattern position. This might allow the |
That looks interesting. I made a quick test, but Rust 1.45 still complains match oid {
oid!(1.2.840.113549.1.1.1) => true,
_ => false,
} gives the following error: 18 | oid!(1.2.840.113549.1.1.1) => true,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected pattern
| in this macro invocation
| this macro call doesn't expand to a pattern (tried adding |
With rust-lang/rust#76001 we could (probably?) get match oid {
oid!(1.2.840.113549.1.1.1) => ...
} The proc macro would then generate the code The match oid.bytes() {
oid!(raw 1.2.840.113549.1.1.1) => ...
} This increases the minimum Rust version supported to 1.45. |
Transferring issue to |
(March 2023) using The problem is related to the fact building an |
Would replacing the current OID implementation with const-oid help here? I've had good results with |
I have a branch here, where I added a full I'll make a new experiment, trying to create an abstraction over |
Currently, if I want to compare parsed OIDs against expected constants, the best I can do with the current API is the following:
If
Oid::from
was aconst fn
, then we could define the constants using something like:This probably requires rusticata/der-parser#17.
The text was updated successfully, but these errors were encountered: