use std::io::ErrorKind;
use rustls_pemfile::{read_one, Item};
pub fn parse_certs(
rd: &mut dyn std::io::BufRead,
) -> Result<Vec<rustls_pki_types::CertificateDer<'static>>, std::io::Error> {
let mut certs = Vec::new();
loop {
let Some(item) = read_one(rd)? else {
return Ok(certs);
};
if let Item::X509Certificate(cert) = item {
certs.push(cert);
}
}
}
pub fn parse_key(
rd: &mut dyn std::io::BufRead,
) -> Result<rustls_pki_types::PrivateKeyDer<'static>, std::io::Error> {
let key = loop {
let Some(item) = read_one(rd)? else {
return Err(std::io::Error::new(
ErrorKind::NotFound,
"no key found in the given data".to_string(),
));
};
if let Some(key) = private_key_from_pemfile_item(item) {
break key;
}
};
loop {
let Some(item) = read_one(rd)? else {
break;
};
if private_key_from_pemfile_item(item).is_some() {
return Err(std::io::Error::new(
ErrorKind::InvalidInput,
"more than one key".to_string(),
));
}
}
Ok(key)
}
fn private_key_from_pemfile_item(
item: rustls_pemfile::Item,
) -> Option<rustls_pki_types::PrivateKeyDer<'static>> {
Some(match item {
Item::Pkcs1Key(key) => key.into(),
Item::Pkcs8Key(key) => key.into(),
Item::Sec1Key(key) => key.into(),
_ => return None,
})
}