Skip to content

Commit

Permalink
Lint: split Lint result and definition, store definitions in registry
Browse files Browse the repository at this point in the history
  • Loading branch information
chifflier committed Jan 24, 2025
1 parent ca9f6aa commit 2ac6b69
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 144 deletions.
5 changes: 2 additions & 3 deletions examples/print-cert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,8 @@ fn print_x509_info(x509: &X509Certificate) -> io::Result<()> {
}
let lints_registry = rfc_lints();
let results = lints_registry.run_lints(x509);
for lint_result in &results {
let def = &lint_result.definition;
eprint!("[{}] {}", lint_result.status, def.name());
for (lint_def, lint_result) in &results {
eprint!("[{}] {}", lint_result.status, lint_def.name());
if let Some(details) = lint_result.details.as_ref() {
eprintln!(" details:{}", details);
}
Expand Down
25 changes: 10 additions & 15 deletions src/lint/certificate_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,17 @@ pub type CertificateLint = fn(_x509: &X509Certificate) -> LintResult;
/// If $link_fn returns true, emit lint warning
#[macro_export]
macro_rules! certificate_lint {
($lint_fn:ident, $lint_name:expr, $lint_description:expr, $lvl:expr, $lint:expr) => (
certificate_lint!(pub(crate) $lint_fn, $lint_name, $lint_description, $lvl, $lint);
($lint_fn:ident, $lvl:expr, $lint:expr) => (
certificate_lint!(pub(crate) $lint_fn, $lvl, $lint);
);
($vis:vis $lint_fn:ident, $lint_name:expr, $lint_description:expr, $lvl:expr, $lint:expr) => {
($vis:vis $lint_fn:ident, $lvl:expr, $lint:expr) => {
$vis fn $lint_fn(x509: &$crate::X509Certificate) -> LintResult {
const DEF: $crate::lint::LintDefinition =
$crate::lint::LintDefinition::new($lint_name, $lint_description);
let f = $lint;
if f(x509) {
// eprintln!("lint fail: {}", $lint_name);
$crate::lint::LintResult::new($lvl, &DEF)
$crate::lint::LintResult::new($lvl)
} else {
$crate::lint::LintResult::new_pass(&DEF)
$crate::lint::LintResult::pass()
}
}
};
Expand All @@ -31,14 +29,11 @@ macro_rules! certificate_lint {
mod tests {
use super::*;

// test macro for lint definition
certificate_lint!(
test_lint1,
"name",
"description",
LintStatus::Error,
|x509: &X509Certificate| x509.version.0 >= 3
);
// test macro for certificate lint definition
certificate_lint!(test_lint1, LintStatus::Error, |x509: &X509Certificate| x509
.version
.0
>= 3);

#[test]
fn test_cert_macro() {
Expand Down
18 changes: 16 additions & 2 deletions src/lint/definition.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct LintDefinition<'a> {
pub(crate) name: &'a str,
pub(crate) description: &'a str,
Expand All @@ -21,10 +21,24 @@ impl<'a> LintDefinition<'a> {
}
}

/// Helper macro to define a new lint
#[macro_export]
macro_rules! lint_definition {
($lint_def:ident, $lint_name:expr, $lint_description:expr) => (
lint_definition!(pub(crate) $lint_def, $lint_name, $lint_description);
);
($vis:vis $lint_def:ident, $lint_name:expr, $lint_description:expr) => {
$vis const $lint_def: $crate::lint::LintDefinition =
$crate::lint::LintDefinition::new($lint_name, $lint_description);
};
}

#[cfg(test)]
mod tests {
use super::*;

// test definition
static _DEF1: LintDefinition = LintDefinition::new("name", "description");
const _DEF1: LintDefinition = LintDefinition::new("name", "description");

lint_definition!(_DEF2, "name", "description");
}
29 changes: 16 additions & 13 deletions src/lint/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,39 @@ use super::*;

#[allow(missing_debug_implementations)]
#[derive(Default)]
pub struct LintRegistry {
pub struct LintRegistry<'a> {
// lints: Vec<LintDefinition>,
lints: Vec<CertificateLint>,
lints: Vec<(LintDefinition<'a>, CertificateLint)>,
}

impl LintRegistry {
pub fn new(lints: Vec<CertificateLint>) -> Self {
impl<'a> LintRegistry<'a> {
pub fn new(lints: Vec<(LintDefinition<'a>, CertificateLint)>) -> Self {
Self { lints }
}

pub fn lints(&self) -> impl Iterator<Item = &CertificateLint> {
self.lints.iter()
}
// pub fn lints(&self) -> impl Iterator<Item = &CertificateLint> {
// self.lints.iter()
// }

pub fn insert(&mut self, lint: CertificateLint) {
self.lints.push(lint);
pub fn insert(&mut self, lint_definition: LintDefinition<'a>, lint: CertificateLint) {
self.lints.push((lint_definition, lint));
}

pub fn merge(&mut self, mut other: LintRegistry) {
pub fn merge(&mut self, mut other: LintRegistry<'a>) {
self.lints.append(&mut other.lints);
}

pub fn run_lints(&self, x509: &X509Certificate) -> Vec<LintResult> {
pub fn run_lints(
&'a self,
x509: &X509Certificate,
) -> Vec<(&'a LintDefinition<'a>, LintResult)> {
self.lints
.iter()
.filter_map(|lint| {
.filter_map(|(lint_definition, lint)| {
let r = (*lint)(x509);
match r.status {
LintStatus::Pass => None,
_ => Some(r),
_ => Some((lint_definition, r)),
}
})
.collect()
Expand Down
33 changes: 9 additions & 24 deletions src/lint/result.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,38 @@
use core::fmt;

use super::{LintDefinition, LintStatus};
use super::LintStatus;

#[derive(Debug)]
pub struct LintResult {
/// Lint status: pass, fail, etc.
pub status: LintStatus,
/// Lint definition
pub definition: &'static LintDefinition<'static>,
/// Lint details (optional)
pub details: Option<LintDetails>,
}

impl LintResult {
#[inline]
pub const fn new(status: LintStatus, definition: &'static LintDefinition<'static>) -> Self {
pub const fn new(status: LintStatus) -> Self {
Self {
status,
definition,
details: None,
}
}

#[inline]
pub const fn new_details(
status: LintStatus,
definition: &'static LintDefinition<'static>,
details: LintDetails,
) -> Self {
pub const fn new_details(status: LintStatus, details: LintDetails) -> Self {
Self {
status,
definition,

details: Some(details),
}
}

#[inline]
pub const fn new_pass(definition: &'static LintDefinition<'static>) -> Self {
pub const fn pass() -> Self {
Self {
status: LintStatus::Pass,
definition,

details: None,
}
}
Expand Down Expand Up @@ -69,16 +62,8 @@ impl fmt::Display for LintDetails {
}
}

#[cfg(test)]
mod tests {
use super::*;

// test definition
const DEF1: LintDefinition = LintDefinition::new("name", "description");

#[test]
fn lint_result() {
//
let _result = LintResult::new(LintStatus::Pass, &DEF1);
impl From<&str> for LintDetails {
fn from(value: &str) -> Self {
LintDetails::new(value.to_string())
}
}
Loading

0 comments on commit 2ac6b69

Please sign in to comment.