use crate::DnsNameRef;
use super::ip_address::{self, IpAddrRef};
#[derive(Debug, Clone, Copy)]
pub enum SubjectNameRef<'a> {
DnsName(DnsNameRef<'a>),
IpAddress(IpAddrRef<'a>),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct InvalidSubjectNameError;
impl<'a> SubjectNameRef<'a> {
pub fn try_from_ascii(subject_name: &'a [u8]) -> Result<Self, InvalidSubjectNameError> {
if let Ok(ip_address) = ip_address::parse_ipv4_address(subject_name) {
return Ok(SubjectNameRef::IpAddress(ip_address));
} else if let Ok(ip_address) = ip_address::parse_ipv6_address(subject_name) {
return Ok(SubjectNameRef::IpAddress(ip_address));
} else {
Ok(SubjectNameRef::DnsName(
DnsNameRef::try_from_ascii(subject_name).map_err(|_| InvalidSubjectNameError)?,
))
}
}
pub fn try_from_ascii_str(subject_name: &'a str) -> Result<Self, InvalidSubjectNameError> {
Self::try_from_ascii(subject_name.as_bytes())
}
}
impl<'a> From<DnsNameRef<'a>> for SubjectNameRef<'a> {
fn from(dns_name: DnsNameRef<'a>) -> SubjectNameRef {
SubjectNameRef::DnsName(DnsNameRef(dns_name.0))
}
}
impl<'a> From<IpAddrRef<'a>> for SubjectNameRef<'a> {
fn from(dns_name: IpAddrRef<'a>) -> SubjectNameRef {
match dns_name {
IpAddrRef::V4(ip_address, ip_address_octets) => {
SubjectNameRef::IpAddress(IpAddrRef::V4(ip_address, ip_address_octets))
}
IpAddrRef::V6(ip_address, ip_address_octets) => {
SubjectNameRef::IpAddress(IpAddrRef::V6(ip_address, ip_address_octets))
}
}
}
}
impl AsRef<[u8]> for SubjectNameRef<'_> {
#[inline]
fn as_ref(&self) -> &[u8] {
match self {
SubjectNameRef::DnsName(dns_name) => dns_name.0,
SubjectNameRef::IpAddress(ip_address) => match ip_address {
IpAddrRef::V4(ip_address, _) | IpAddrRef::V6(ip_address, _) => ip_address,
},
}
}
}