use super::rdata::RData;
use super::types::{RecordClass, RecordType};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResourceRecord {
name: String,
rtype: RecordType,
rclass: RecordClass,
ttl: u32,
rdata: RData,
}
impl ResourceRecord {
pub fn new(
name: String,
rtype: RecordType,
rclass: RecordClass,
ttl: u32,
rdata: RData,
) -> Self {
Self {
name,
rtype,
rclass,
ttl,
rdata,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn rtype(&self) -> RecordType {
self.rtype
}
pub fn rclass(&self) -> RecordClass {
self.rclass
}
pub fn ttl(&self) -> u32 {
self.ttl
}
pub fn rdata(&self) -> &RData {
&self.rdata
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
pub fn set_rtype(&mut self, rtype: RecordType) {
self.rtype = rtype;
}
pub fn set_rclass(&mut self, rclass: RecordClass) {
self.rclass = rclass;
}
pub fn set_ttl(&mut self, ttl: u32) {
self.ttl = ttl;
}
pub fn set_rdata(&mut self, rdata: RData) {
self.rdata = rdata;
}
}
impl fmt::Display for ResourceRecord {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}\t{}\t{}\t{}\t{}",
self.name, self.ttl, self.rclass, self.rtype, self.rdata
)
}
}
pub type Record = ResourceRecord;
#[cfg(test)]
mod tests {
use super::*;
use std::net::Ipv4Addr;
#[test]
fn test_resource_record_creation() {
let record = ResourceRecord::new(
"example.com".to_string(),
RecordType::A,
RecordClass::IN,
3600,
RData::A(Ipv4Addr::new(192, 0, 2, 1)),
);
assert_eq!(record.name(), "example.com");
assert_eq!(record.rtype(), RecordType::A);
assert_eq!(record.rclass(), RecordClass::IN);
assert_eq!(record.ttl(), 3600);
}
#[test]
fn test_resource_record_setters() {
let mut record = ResourceRecord::new(
"example.com".to_string(),
RecordType::A,
RecordClass::IN,
3600,
RData::A(Ipv4Addr::new(192, 0, 2, 1)),
);
record.set_name("test.com".to_string());
record.set_rtype(RecordType::AAAA);
record.set_rclass(RecordClass::CH);
record.set_ttl(7200);
assert_eq!(record.name(), "test.com");
assert_eq!(record.rtype(), RecordType::AAAA);
assert_eq!(record.rclass(), RecordClass::CH);
assert_eq!(record.ttl(), 7200);
}
#[test]
fn test_resource_record_display() {
let record = ResourceRecord::new(
"example.com".to_string(),
RecordType::A,
RecordClass::IN,
3600,
RData::A(Ipv4Addr::new(192, 0, 2, 1)),
);
let display = format!("{}", record);
assert!(display.contains("example.com"));
assert!(display.contains("3600"));
assert!(display.contains("IN"));
assert!(display.contains("A"));
assert!(display.contains("192.0.2.1"));
}
#[test]
fn test_record_equality() {
let r1 = ResourceRecord::new(
"example.com".to_string(),
RecordType::A,
RecordClass::IN,
3600,
RData::A(Ipv4Addr::new(192, 0, 2, 1)),
);
let r2 = ResourceRecord::new(
"example.com".to_string(),
RecordType::A,
RecordClass::IN,
3600,
RData::A(Ipv4Addr::new(192, 0, 2, 1)),
);
let r3 = ResourceRecord::new(
"other.com".to_string(),
RecordType::A,
RecordClass::IN,
3600,
RData::A(Ipv4Addr::new(192, 0, 2, 1)),
);
assert_eq!(r1, r2);
assert_ne!(r1, r3);
}
#[test]
fn test_different_record_types() {
use std::net::Ipv6Addr;
let aaaa = ResourceRecord::new(
"example.com".to_string(),
RecordType::AAAA,
RecordClass::IN,
3600,
RData::AAAA(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
);
assert_eq!(aaaa.rtype(), RecordType::AAAA);
let cname = ResourceRecord::new(
"www.example.com".to_string(),
RecordType::CNAME,
RecordClass::IN,
3600,
RData::CNAME("example.com".to_string()),
);
assert_eq!(cname.rtype(), RecordType::CNAME);
let mx = ResourceRecord::new(
"example.com".to_string(),
RecordType::MX,
RecordClass::IN,
3600,
RData::mx(10, "mail.example.com".to_string()),
);
assert_eq!(mx.rtype(), RecordType::MX);
}
}