#![no_std]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
pub struct Cert {
subject_hash: u32,
seq: u8,
der: &'static [u8],
subject: &'static [u8],
label: &'static str,
}
impl Cert {
const fn new(
subject_hash: u32,
seq: u8,
der: &'static [u8],
subject: &'static [u8],
label: &'static str,
) -> Self {
Cert {
subject_hash,
seq,
der,
subject,
label,
}
}
pub const fn der(&self) -> &'static [u8] {
self.der
}
pub const fn subject_der(&self) -> &'static [u8] {
self.subject
}
pub const fn subject_hash(&self) -> u32 {
self.subject_hash
}
pub const fn seq(&self) -> u8 {
self.seq
}
pub const fn label(&self) -> &'static str {
self.label
}
pub const fn hash_name(&self) -> HashName {
HashName {
hash: self.subject_hash,
seq: self.seq,
}
}
}
impl core::fmt::Debug for Cert {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Cert")
.field("name", &format_args!("{}", self.hash_name()))
.field("label", &self.label)
.field("der_len", &self.der.len())
.finish()
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct HashName {
hash: u32,
seq: u8,
}
impl core::fmt::Display for HashName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:08x}.{}", self.hash, self.seq)
}
}
impl core::fmt::Debug for HashName {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Display::fmt(self, f)
}
}
include!(concat!(env!("OUT_DIR"), "/certs.rs"));
pub fn all() -> &'static [Cert] {
CERTS
}
pub fn len() -> usize {
CERTS.len()
}
pub fn lookup_by_hash(hash: u32) -> &'static [Cert] {
let lo = CERTS.partition_point(|c| c.subject_hash < hash);
let hi = CERTS.partition_point(|c| c.subject_hash <= hash);
&CERTS[lo..hi]
}
pub fn lookup(name: &str) -> Option<&'static Cert> {
let (hash_str, seq_str) = name.split_once('.')?;
if hash_str.len() != 8 {
return None;
}
let hash = u32::from_str_radix(hash_str, 16).ok()?;
let seq: u8 = seq_str.parse().ok()?;
lookup_by_hash(hash).iter().find(|c| c.seq == seq)
}
pub fn find_by_subject<'a>(subject_der: &'a [u8]) -> impl Iterator<Item = &'static Cert> + 'a {
CERTS.iter().filter(move |c| c.subject == subject_der)
}