use serde::{Deserialize, Serialize};
use crate::prelude::{to_opt_vec, Remark, Remarks};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Ttl0Data {
pub values: Values,
#[serde(skip_serializing_if = "Option::is_none")]
pub remarks: Option<Remarks>,
}
#[buildstructor::buildstructor]
impl Ttl0Data {
#[builder(visibility = "pub")]
fn new(
ns_value: Option<u32>,
ds_value: Option<u32>,
a_value: Option<u32>,
aaaa_value: Option<u32>,
mx_value: Option<u32>,
ptr_value: Option<u32>,
cname_value: Option<u32>,
cds_value: Option<u32>,
csync_value: Option<u32>,
caa_value: Option<u32>,
dnskey_value: Option<u32>,
cert_value: Option<u32>,
cdnskey_value: Option<u32>,
https_value: Option<u32>,
key_value: Option<u32>,
naptr_value: Option<u32>,
srv_value: Option<u32>,
svcb_value: Option<u32>,
tlsa_value: Option<u32>,
txt_value: Option<u32>,
uri_value: Option<u32>,
remarks: Vec<Remark>,
) -> Self {
Self {
values: Values {
ns: ns_value,
ds: ds_value,
a: a_value,
aaaa: aaaa_value,
mx: mx_value,
ptr: ptr_value,
cname: cname_value,
cds: cds_value,
csync: csync_value,
caa: caa_value,
dnskey: dnskey_value,
cert: cert_value,
cdnskey: cdnskey_value,
https: https_value,
key: key_value,
naptr: naptr_value,
srv: srv_value,
svcb: svcb_value,
tlsa: tlsa_value,
txt: txt_value,
uri: uri_value,
},
remarks: to_opt_vec(remarks),
}
}
pub fn a_value(&self) -> Option<u32> {
self.values.a
}
pub fn aaaa_value(&self) -> Option<u32> {
self.values.aaaa
}
pub fn ns_value(&self) -> Option<u32> {
self.values.ns
}
pub fn ds_value(&self) -> Option<u32> {
self.values.ds
}
pub fn mx_value(&self) -> Option<u32> {
self.values.mx
}
pub fn ptr_value(&self) -> Option<u32> {
self.values.ptr
}
pub fn cname_value(&self) -> Option<u32> {
self.values.cname
}
pub fn cds_value(&self) -> Option<u32> {
self.values.cds
}
pub fn csync_value(&self) -> Option<u32> {
self.values.csync
}
pub fn caa_value(&self) -> Option<u32> {
self.values.caa
}
pub fn dnskey_value(&self) -> Option<u32> {
self.values.dnskey
}
pub fn cert_value(&self) -> Option<u32> {
self.values.cert
}
pub fn cdnskey_value(&self) -> Option<u32> {
self.values.cdnskey
}
pub fn https_value(&self) -> Option<u32> {
self.values.https
}
pub fn key_value(&self) -> Option<u32> {
self.values.key
}
pub fn naptr_value(&self) -> Option<u32> {
self.values.naptr
}
pub fn srv_value(&self) -> Option<u32> {
self.values.srv
}
pub fn svcb_value(&self) -> Option<u32> {
self.values.svcb
}
pub fn tlsa_value(&self) -> Option<u32> {
self.values.tlsa
}
pub fn txt_value(&self) -> Option<u32> {
self.values.txt
}
pub fn uri_value(&self) -> Option<u32> {
self.values.uri
}
pub fn remarks(&self) -> &[Remark] {
self.remarks.as_deref().unwrap_or_default()
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Values {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "NS")]
pub ns: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "DS")]
pub ds: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "A")]
pub a: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "AAAA")]
pub aaaa: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "MX")]
pub mx: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "PTR")]
pub ptr: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "CNAME")]
pub cname: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "CDS")]
pub cds: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "CSYNC")]
pub csync: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "CAA")]
pub caa: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "DNSKEY")]
pub dnskey: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "CERT")]
pub cert: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "CDNSKEY")]
pub cdnskey: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "HTTPS")]
pub https: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "KEY")]
pub key: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "NAPTR")]
pub naptr: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "SRV")]
pub srv: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "SVCB")]
pub svcb: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "TLSA")]
pub tlsa: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "TXT")]
pub txt: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "URI")]
pub uri: Option<u32>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::Remark;
#[test]
fn test_ttl_builder_with_all_records() {
let ttl = Ttl0Data::builder()
.ns_value(100)
.ds_value(200)
.a_value(300)
.aaaa_value(400)
.mx_value(500)
.ptr_value(600)
.cname_value(700)
.cds_value(800)
.csync_value(900)
.caa_value(1000)
.dnskey_value(1100)
.cert_value(1200)
.cdnskey_value(1300)
.https_value(1400)
.key_value(1500)
.naptr_value(1600)
.srv_value(1700)
.svcb_value(1800)
.tlsa_value(1900)
.txt_value(2000)
.uri_value(2100)
.build();
assert_eq!(ttl.ns_value(), Some(100));
assert_eq!(ttl.ds_value(), Some(200));
assert_eq!(ttl.a_value(), Some(300));
assert_eq!(ttl.aaaa_value(), Some(400));
assert_eq!(ttl.mx_value(), Some(500));
assert_eq!(ttl.ptr_value(), Some(600));
assert_eq!(ttl.cname_value(), Some(700));
assert_eq!(ttl.cds_value(), Some(800));
assert_eq!(ttl.csync_value(), Some(900));
assert_eq!(ttl.caa_value(), Some(1000));
assert_eq!(ttl.dnskey_value(), Some(1100));
assert_eq!(ttl.cert_value(), Some(1200));
assert_eq!(ttl.cdnskey_value(), Some(1300));
assert_eq!(ttl.https_value(), Some(1400));
assert_eq!(ttl.key_value(), Some(1500));
assert_eq!(ttl.naptr_value(), Some(1600));
assert_eq!(ttl.srv_value(), Some(1700));
assert_eq!(ttl.svcb_value(), Some(1800));
assert_eq!(ttl.tlsa_value(), Some(1900));
assert_eq!(ttl.txt_value(), Some(2000));
assert_eq!(ttl.uri_value(), Some(2100));
}
#[test]
fn test_ttl_with_remarks() {
let remark = Remark::builder()
.description(vec!["Test remark".to_string()])
.build();
let ttl = Ttl0Data::builder()
.a_value(300)
.remarks(vec![remark])
.build();
assert_eq!(ttl.a_value(), Some(300));
assert_eq!(ttl.remarks().len(), 1);
assert!(ttl.remarks()[0].description.is_some());
}
#[test]
fn test_ttl_builder_empty() {
let ttl = Ttl0Data::builder().build();
assert_eq!(ttl.ns_value(), None);
assert_eq!(ttl.ds_value(), None);
assert_eq!(ttl.a_value(), None);
assert_eq!(ttl.aaaa_value(), None);
assert_eq!(ttl.mx_value(), None);
assert_eq!(ttl.ptr_value(), None);
assert_eq!(ttl.cname_value(), None);
assert_eq!(ttl.cds_value(), None);
assert_eq!(ttl.csync_value(), None);
assert_eq!(ttl.caa_value(), None);
assert_eq!(ttl.dnskey_value(), None);
assert_eq!(ttl.cert_value(), None);
assert_eq!(ttl.cdnskey_value(), None);
assert_eq!(ttl.https_value(), None);
assert_eq!(ttl.key_value(), None);
assert_eq!(ttl.naptr_value(), None);
assert_eq!(ttl.srv_value(), None);
assert_eq!(ttl.svcb_value(), None);
assert_eq!(ttl.tlsa_value(), None);
assert_eq!(ttl.txt_value(), None);
assert_eq!(ttl.uri_value(), None);
}
#[test]
fn test_ttl_serialization() {
let ttl = Ttl0Data::builder()
.a_value(300)
.mx_value(500)
.txt_value(2000)
.build();
let json = serde_json::to_string(&ttl).unwrap();
let parsed: Ttl0Data = serde_json::from_str(&json).unwrap();
assert_eq!(ttl, parsed);
assert_eq!(parsed.a_value(), Some(300));
assert_eq!(parsed.mx_value(), Some(500));
assert_eq!(parsed.txt_value(), Some(2000));
}
#[test]
fn test_json_serialization_format() {
let ttl = Ttl0Data::builder()
.a_value(300)
.mx_value(500)
.txt_value(2000)
.build();
let json = serde_json::to_string_pretty(&ttl).unwrap();
assert!(json.contains("\"A\": 300"));
assert!(json.contains("\"MX\": 500"));
assert!(json.contains("\"TXT\": 2000"));
assert!(!json.contains("\"NS\""));
assert!(!json.contains("\"DS\""));
assert!(!json.contains("\"AAAA\""));
}
}