Skip to content
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

Concatenate a OIDs #45

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@
//! (DER)."

#![deny(/*missing_docs,*/
unstable_features,
/*unstable_features,*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really would prefer not to do this (see below)

unused_import_braces,
unused_qualifications,
unreachable_pub)]
Expand All @@ -225,9 +225,11 @@
no_crate_inject,
attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
))]
#![feature(const_precise_live_drops)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this prevents from building with stable rustc, which would not be acceptable.
Why is it required ? I see no code using it (at least in rustc 1.53, bytes_from_borrowed does not require it)


#[macro_use]
mod macros;
mod oid_append;

#[allow(clippy::module_inception)]
pub mod ber;
Expand Down
9 changes: 9 additions & 0 deletions src/oid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ impl<'a> Oid<'a> {
}
}

/// Get the encoded oid without the header. Const version.
/// Only works when memory is not allocated on the heap, otherwise it returns an empty array.
pub const fn bytes_from_borrowed(&self) -> &[u8] {
match &self.asn1 {
Cow::Borrowed(b) => *b,
_ => &[],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what the best behavior is:

  • returning an empty slice hides the error, which may be bad
  • this is a const fn, so we can't panic (an ugly way to do that would be to do something like {"error message"[256]; &[]} so at least we get an error message

}
}

/// Build an OID from an array of object identifier components.
/// This method allocates memory on the heap.
// we do not use .copied() for compatibility with 1.34
Expand Down
88 changes: 88 additions & 0 deletions src/oid_append.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/// Internal OID arrays concatenation.
#[doc(hidden)]
#[macro_export]
macro_rules! array_concat(
($first:expr, $second:expr) => {
&{
let mut x = [0; $first.len() + 1 + $second.len()];

let mut i = 0;
while i < $first.len() {
x[i] = $first[i];
i += 1;
}

x[$first.len()] = $second[0] / 40;
x[$first.len() + 1] = $second[0] % 40;
let start = $first.len() + 1;

let mut i = 1;
while i < $second.len() {
x[start + i] = $second[i];
i += 1;
}

x
}
};
);

/// Create OID from two others.
#[macro_export]
macro_rules! oid_append(
// oid_append!(A, B)
($parent:ident, $appendix:ident) => ({
const CONCATENATED: &[u8] = der_parser::array_concat!(
&$parent.bytes_from_borrowed(),
&$appendix.bytes_from_borrowed()
);
Oid::new(std::borrow::Cow::Borrowed(CONCATENATED))
});

// oid_append!(A, 3.4)
($parent:expr, $appendix_start:tt$(.$appendix_item:tt)*) => ({
const PARENT: Oid = $parent;
const APPENDIX: Oid = oid!($appendix_start$(.$appendix_item)*);
oid_append!(PARENT, APPENDIX)
});

// oid_append!(oid!(1.2), oid!(3.4))
($parent:expr, $appendix:expr) => ({
const PARENT: Oid = $parent;
const APPENDIX: Oid = $appendix;
oid_append!(PARENT, APPENDIX)
});
);

#[cfg(test)]
mod tests {
use crate::oid;
use crate::oid::Oid;
// oid!() macro used crate as `der_parser`
use crate as der_parser;

const A: Oid = oid!(1.2.3);
const B: Oid = oid_append!(A, 4.5);
const C: Oid = oid_append!(A, B);
const D: Oid = oid_append!(C, C);

#[test]
#[rustfmt::skip]
fn test_oid_inheritance() {
assert_eq!(B, oid!(1.2.3.4.5));
assert_eq!(C, oid!(1.2.3.1.2.3.4.5));
assert_eq!(D, oid!(1.2.3.1.2.3.4.5.1.2.3.1.2.3.4.5));
}

const E: Oid = oid_append!(oid!(1.2.3), oid!(3.0));
const F: Oid = oid_append!(oid!(0.0.3), oid!(0.3.0));
const G: Oid = oid_append!(oid!(3.7.32452), oid!(2.29.34536));

#[test]
#[rustfmt::skip]
fn test_oid_correct_concatenated() {
assert_eq!(E, oid!(1.2.3.3.0));
assert_eq!(F, oid!(0.0.3.0.3.0));
assert_eq!(G, oid!(3.7.32452.2.29.34536));
}
}