use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder};
use serde::{Deserialize, Serialize};
use crate::general_names::{
general_name::{GeneralName, GeneralNameTypeRegistry, GeneralNameValue},
GeneralNames,
};
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct AlternativeName(GeneralNamesOrText);
impl AlternativeName {
#[must_use]
pub fn new(value: GeneralNamesOrText) -> Self {
Self(value)
}
#[must_use]
pub fn get_inner(&self) -> &GeneralNamesOrText {
&self.0
}
}
impl Encode<()> for AlternativeName {
fn encode<W: Write>(
&self, e: &mut Encoder<W>, ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
self.0.encode(e, ctx)
}
}
impl Decode<'_, ()> for AlternativeName {
fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result<Self, minicbor::decode::Error> {
GeneralNamesOrText::decode(d, ctx).map(AlternativeName::new)
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum GeneralNamesOrText {
GeneralNames(GeneralNames),
Text(String),
}
impl Encode<()> for GeneralNamesOrText {
fn encode<W: Write>(
&self, e: &mut Encoder<W>, ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
GeneralNamesOrText::GeneralNames(gns) => {
let gn = gns
.get_inner()
.first()
.ok_or(minicbor::encode::Error::message("GeneralNames is empty"))?;
if gns.get_inner().len() == 1 && gn.get_gn_type().is_dns_name() {
gn.get_gn_value().encode(e, ctx)?;
} else {
gns.encode(e, ctx)?;
}
},
GeneralNamesOrText::Text(text) => {
e.str(text)?;
},
}
Ok(())
}
}
impl Decode<'_, ()> for GeneralNamesOrText {
fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result<Self, minicbor::decode::Error> {
match d.datatype()? {
minicbor::data::Type::String => {
let gn_dns = GeneralName::new(
GeneralNameTypeRegistry::DNSName,
GeneralNameValue::Text(d.str()?.to_string()),
);
let mut gns = GeneralNames::new();
gns.add_gn(gn_dns);
Ok(GeneralNamesOrText::GeneralNames(gns))
},
minicbor::data::Type::Array => {
Ok(GeneralNamesOrText::GeneralNames(GeneralNames::decode(
d, ctx,
)?))
},
_ => {
Err(minicbor::decode::Error::message(
"Invalid type for AlternativeName",
))
},
}
}
}
#[cfg(test)]
mod test_alt_name {
use super::*;
use crate::general_names::general_name::{
GeneralName, GeneralNameTypeRegistry, GeneralNameValue,
};
#[test]
fn encode_only_dns() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let mut gns = GeneralNames::new();
gns.add_gn(GeneralName::new(
GeneralNameTypeRegistry::DNSName,
GeneralNameValue::Text("example.com".to_string()),
));
let alt_name = AlternativeName::new(GeneralNamesOrText::GeneralNames(gns));
alt_name
.encode(&mut encoder, &mut ())
.expect("Failed to encode AlternativeName");
assert_eq!(hex::encode(buffer.clone()), "6b6578616d706c652e636f6d");
let mut decoder = Decoder::new(&buffer);
let decoded_alt_name = AlternativeName::decode(&mut decoder, &mut ())
.expect("Failed to decode Alternative Name");
assert_eq!(decoded_alt_name, alt_name);
}
#[test]
fn encode_decode_text() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);
let alt_name = AlternativeName::new(GeneralNamesOrText::Text("example.com".to_string()));
alt_name
.encode(&mut encoder, &mut ())
.expect("Failed to encode AlternativeName");
assert_eq!(hex::encode(buffer.clone()), "6b6578616d706c652e636f6d");
let mut gns = GeneralNames::new();
gns.add_gn(GeneralName::new(
GeneralNameTypeRegistry::DNSName,
GeneralNameValue::Text("example.com".to_string()),
));
let mut decoder = Decoder::new(&buffer);
let decoded_alt_name = AlternativeName::decode(&mut decoder, &mut ())
.expect("Failed to decode Alternative Name");
assert_eq!(
decoded_alt_name,
AlternativeName::new(GeneralNamesOrText::GeneralNames(gns))
);
}
}