use std::fmt;
#[cfg(feature = "serde-config")]
use serde::{Deserialize, Serialize};
use crate::error::*;
use crate::rr::type_bit_map::{decode_type_bit_maps, encode_type_bit_maps};
use crate::rr::{Name, RecordType};
use crate::serialize::binary::*;
#[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct NSEC {
next_domain_name: Name,
type_bit_maps: Vec<RecordType>,
}
impl NSEC {
pub fn new(next_domain_name: Name, type_bit_maps: Vec<RecordType>) -> Self {
Self {
next_domain_name,
type_bit_maps,
}
}
pub fn new_cover_self(next_domain_name: Name, mut type_bit_maps: Vec<RecordType>) -> Self {
type_bit_maps.push(RecordType::NSEC);
Self::new(next_domain_name, type_bit_maps)
}
pub fn next_domain_name(&self) -> &Name {
&self.next_domain_name
}
pub fn type_bit_maps(&self) -> &[RecordType] {
&self.type_bit_maps
}
}
pub fn read(decoder: &mut BinDecoder<'_>, rdata_length: Restrict<u16>) -> ProtoResult<NSEC> {
let start_idx = decoder.index();
let next_domain_name = Name::read(decoder)?;
let bit_map_len = rdata_length
.map(|u| u as usize)
.checked_sub(decoder.index() - start_idx)
.map_err(|_| ProtoError::from("invalid rdata length in NSEC"))?;
let record_types = decode_type_bit_maps(decoder, bit_map_len)?;
Ok(NSEC::new(next_domain_name, record_types))
}
pub fn emit(encoder: &mut BinEncoder<'_>, rdata: &NSEC) -> ProtoResult<()> {
encoder.with_canonical_names(|encoder| {
rdata.next_domain_name().emit(encoder)?;
encode_type_bit_maps(encoder, rdata.type_bit_maps())
})
}
impl fmt::Display for NSEC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.next_domain_name)?;
for ty in &self.type_bit_maps {
write!(f, " {}", ty)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::dbg_macro, clippy::print_stdout)]
use super::*;
#[test]
fn test() {
use crate::rr::RecordType;
use std::str::FromStr;
let rdata = NSEC::new(
Name::from_str("www.example.com").unwrap(),
vec![
RecordType::A,
RecordType::AAAA,
RecordType::DS,
RecordType::RRSIG,
],
);
let mut bytes = Vec::new();
let mut encoder: BinEncoder<'_> = BinEncoder::new(&mut bytes);
assert!(emit(&mut encoder, &rdata).is_ok());
let bytes = encoder.into_bytes();
println!("bytes: {:?}", bytes);
let mut decoder: BinDecoder<'_> = BinDecoder::new(bytes);
let restrict = Restrict::new(bytes.len() as u16);
let read_rdata = read(&mut decoder, restrict).expect("Decoding error");
assert_eq!(rdata, read_rdata);
}
}