use core::{
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
};
use domain_macros::*;
use crate::{
new::base::{
build::BuildInMessage,
name::NameCompressor,
wire::{AsBytes, BuildBytes, SizePrefixed, TruncationError, U16},
CanonicalRecordData,
},
utils::dst::UnsizedCopy,
};
use super::TypeBitmaps;
#[derive(Clone, Debug, PartialEq, Eq, Hash, BuildBytes, ParseBytes)]
pub struct NSec3<'a> {
pub algorithm: NSec3HashAlg,
pub flags: NSec3Flags,
pub iterations: U16,
pub salt: &'a SizePrefixed<u8, [u8]>,
pub next: &'a SizePrefixed<u8, [u8]>,
pub types: &'a TypeBitmaps,
}
impl NSec3<'_> {
#[cfg(feature = "bumpalo")]
pub fn clone_to_bump<'r>(&self, bump: &'r bumpalo::Bump) -> NSec3<'r> {
use crate::utils::dst::copy_to_bump;
NSec3 {
algorithm: self.algorithm,
flags: self.flags,
iterations: self.iterations,
salt: copy_to_bump(self.salt, bump),
next: copy_to_bump(self.next, bump),
types: copy_to_bump(self.types, bump),
}
}
}
impl CanonicalRecordData for NSec3<'_> {
fn cmp_canonical(&self, that: &Self) -> Ordering {
let this = (
self.algorithm,
self.flags.as_bytes(),
self.iterations,
self.salt.len(),
self.salt,
self.next.len(),
self.next,
self.types.as_bytes(),
);
let that = (
that.algorithm,
that.flags.as_bytes(),
that.iterations,
that.salt.len(),
that.salt,
that.next.len(),
that.next,
that.types.as_bytes(),
);
this.cmp(&that)
}
}
impl BuildInMessage for NSec3<'_> {
fn build_in_message(
&self,
contents: &mut [u8],
start: usize,
_compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
let bytes = contents.get_mut(start..).ok_or(TruncationError)?;
let rest = self.build_bytes(bytes)?.len();
Ok(contents.len() - rest)
}
}
#[derive(
Debug, AsBytes, BuildBytes, ParseBytesZC, SplitBytesZC, UnsizedCopy,
)]
#[repr(C)]
pub struct NSec3Param {
pub algorithm: NSec3HashAlg,
pub flags: NSec3Flags,
pub iterations: U16,
pub salt: SizePrefixed<u8, [u8]>,
}
impl CanonicalRecordData for NSec3Param {
fn cmp_canonical(&self, other: &Self) -> Ordering {
self.as_bytes().cmp(other.as_bytes())
}
}
impl BuildInMessage for NSec3Param {
fn build_in_message(
&self,
contents: &mut [u8],
start: usize,
_compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
let bytes = self.as_bytes();
let end = start + bytes.len();
contents
.get_mut(start..end)
.ok_or(TruncationError)?
.copy_from_slice(bytes);
Ok(end)
}
}
#[cfg(feature = "alloc")]
impl Clone for alloc::boxed::Box<NSec3Param> {
fn clone(&self) -> Self {
(*self).unsized_copy_into()
}
}
impl PartialEq for NSec3Param {
fn eq(&self, other: &Self) -> bool {
self.as_bytes() == other.as_bytes()
}
}
impl Eq for NSec3Param {}
impl Hash for NSec3Param {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write(self.as_bytes())
}
}
#[derive(
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
AsBytes,
BuildBytes,
ParseBytes,
ParseBytesZC,
SplitBytes,
SplitBytesZC,
UnsizedCopy,
)]
#[repr(transparent)]
pub struct NSec3HashAlg {
pub code: u8,
}
impl NSec3HashAlg {
pub const SHA1: Self = Self { code: 1 };
}
impl fmt::Debug for NSec3HashAlg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match *self {
Self::SHA1 => "NSec3HashAlg::SHA1",
_ => return write!(f, "NSec3HashAlg({})", self.code),
})
}
}
#[derive(
Copy,
Clone,
Default,
Hash,
PartialEq,
Eq,
AsBytes,
BuildBytes,
ParseBytes,
ParseBytesZC,
SplitBytes,
SplitBytesZC,
UnsizedCopy,
)]
#[repr(transparent)]
pub struct NSec3Flags {
inner: u8,
}
impl NSec3Flags {
fn get_flag(&self, pos: u32) -> bool {
self.inner & (1 << pos) != 0
}
fn set_flag(mut self, pos: u32, value: bool) -> Self {
self.inner &= !(1 << pos);
self.inner |= (value as u8) << pos;
self
}
pub fn bits(&self) -> u8 {
self.inner
}
pub fn is_optout(&self) -> bool {
self.get_flag(0)
}
pub fn set_optout(self, value: bool) -> Self {
self.set_flag(0, value)
}
}
impl fmt::Debug for NSec3Flags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NSec3Flags")
.field("optout", &self.is_optout())
.field("bits", &self.bits())
.finish()
}
}