From c9e46c66bd0dcccf8e97cc039d0054edc6636cfe Mon Sep 17 00:00:00 2001 From: arya dradjica Date: Thu, 19 Feb 2026 11:15:57 +0100 Subject: [PATCH 1/6] [macros] Remove type defaults from impl block generics Caught while defining 'ZoneMD'. --- macros/src/impls.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/macros/src/impls.rs b/macros/src/impls.rs index 4c0971998..bdb9b9cfa 100644 --- a/macros/src/impls.rs +++ b/macros/src/impls.rs @@ -57,7 +57,12 @@ impl ImplSkeleton { } GenericParam::Type(value) => { - types.push(value.clone()); + types.push(TypeParam { + // Defaults are not allowed in 'impl' blocks. + eq_token: None, + default: None, + ..value.clone() + }); let id = value.ident.clone(); let id = syn::TypePath { qself: None, From eb864166d8f0482fbb167d19e06e07020e752e0e Mon Sep 17 00:00:00 2001 From: arya dradjica Date: Thu, 19 Feb 2026 11:15:57 +0100 Subject: [PATCH 2/6] [new/rdata] Add 'ZoneMD' --- src/new/base/record.rs | 4 + src/new/rdata/mod.rs | 17 +- src/new/rdata/zonemd.rs | 425 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 src/new/rdata/zonemd.rs diff --git a/src/new/base/record.rs b/src/new/base/record.rs index 0d829c745..bf9a6c762 100644 --- a/src/new/base/record.rs +++ b/src/new/base/record.rs @@ -299,6 +299,9 @@ impl RType { /// The type of an [`NSec3Param`](crate::new::rdata::NSec3Param) record. pub const NSEC3PARAM: Self = Self::new(51); + + /// The type of a [`ZoneMD`](crate::new::rdata::ZoneMD) record. + pub const ZONEMD: Self = Self::new(63); } //--- Interaction @@ -389,6 +392,7 @@ impl fmt::Debug for RType { Self::DNSKEY => "RType::DNSKEY", Self::NSEC3 => "RType::NSEC3", Self::NSEC3PARAM => "RType::NSEC3PARAM", + Self::ZONEMD => "RType::ZONEMD", _ => return write!(f, "RType({})", self.code), }) } diff --git a/src/new/rdata/mod.rs b/src/new/rdata/mod.rs index 4974af132..46b852f9e 100644 --- a/src/new/rdata/mod.rs +++ b/src/new/rdata/mod.rs @@ -58,6 +58,9 @@ //! - [`NSec`] //! - [`NSec3`] //! - [`Ds`] +//! +//! ZONEMD support (RFC 8976): +//! - [`ZoneMD`] #![deny(missing_docs)] #![deny(clippy::missing_docs_in_private_items)] @@ -110,6 +113,9 @@ pub use dnssec::{ NSec3HashAlg, NSec3Param, RRSig, SecAlg, TypeBitmaps, }; +mod zonemd; +pub use zonemd::{ZoneMD, ZoneMDHashAlg, ZoneMDScheme}; + use super::base::wire::ParseBytesZC; //----------- RecordData ----------------------------------------------------- @@ -288,7 +294,10 @@ define_record_data! { NSec3(NSec3<'a>) = NSEC3, /// Parameters for computing [`NSec3`] records. - NSec3Param(&'a NSec3Param) = NSEC3PARAM; + NSec3Param(&'a NSec3Param) = NSEC3PARAM, + + /// A message digest of the enclosing zone. + ZoneMD(&'a ZoneMD) = ZONEMD; /// Data for an unknown DNS record type. Unknown(RType, &'a UnknownRecordData) @@ -318,6 +327,7 @@ impl<'a, N> RecordData<'a, N> { Self::DNSKey(r) => RecordData::DNSKey(r), Self::NSec3(r) => RecordData::NSec3(r), Self::NSec3Param(r) => RecordData::NSec3Param(r), + Self::ZoneMD(r) => RecordData::ZoneMD(r), Self::Unknown(rt, rd) => RecordData::Unknown(rt, rd), } } @@ -345,6 +355,7 @@ impl<'a, N> RecordData<'a, N> { Self::DNSKey(r) => RecordData::DNSKey(r), Self::NSec3(r) => RecordData::NSec3(r.clone()), Self::NSec3Param(r) => RecordData::NSec3Param(r), + Self::ZoneMD(r) => RecordData::ZoneMD(r), Self::Unknown(rt, rd) => RecordData::Unknown(*rt, rd), } } @@ -380,6 +391,7 @@ impl<'a, N> RecordData<'a, N> { Self::NSec3Param(r) => { RecordData::NSec3Param(copy_to_bump(*r, bump)) } + Self::ZoneMD(r) => RecordData::ZoneMD(copy_to_bump(*r, bump)), Self::Unknown(rt, rd) => { RecordData::Unknown(*rt, rd.clone_to_bump(bump)) } @@ -444,6 +456,9 @@ impl<'a, N: SplitMessageBytes<'a>> ParseRecordData<'a> for RecordData<'a, N> { <&NSec3Param>::parse_bytes(&contents[start..]) .map(Self::NSec3Param) } + RType::ZONEMD => { + <&ZoneMD>::parse_bytes(&contents[start..]).map(Self::ZoneMD) + } _ => <&UnknownRecordData>::parse_bytes(&contents[start..]) .map(|data| Self::Unknown(rtype, data)), } diff --git a/src/new/rdata/zonemd.rs b/src/new/rdata/zonemd.rs new file mode 100644 index 000000000..4775078d7 --- /dev/null +++ b/src/new/rdata/zonemd.rs @@ -0,0 +1,425 @@ +//! The ZONEMD record type. +//! +//! See [RFC 8976](https://www.rfc-editor.org/rfc/rfc8976.html). + +use core::{cmp::Ordering, fmt}; + +use crate::{ + new::base::{ + build::BuildInMessage, + name::NameCompressor, + wire::{ + AsBytes, BuildBytes, ParseBytes, ParseBytesZC, ParseError, + SplitBytes, SplitBytesZC, TruncationError, + }, + CanonicalRecordData, ParseRecordData, ParseRecordDataBytes, RType, + Serial, + }, + utils::dst::UnsizedCopy, +}; + +//----------- ZoneMD --------------------------------------------------------- + +/// A message digest of the enclosing zone. +/// +/// A [`ZoneMD`] record contains a deterministically computed digest (i.e. +/// cryptographic hash) of the contents of the surrounding zone. It can +/// be used to verify the integrity (and possibly authenticity) of all the +/// records in the zone, including glue records, even at rest. +/// +/// [`ZoneMD`] is specified by [RFC 8976]. As discussed within, it provides +/// unique functionality over other means of checking and authenticating DNS +/// zones; when DNSSEC-signed, it asserts the authenticity of glue records +/// present with the zone. This is especially important for the root zone. +/// +/// [RFC 8976]: https://www.rfc-editor.org/rfc/rfc8976.html +/// +/// ## Computation +/// +/// [`ZoneMD`] specifies a [scheme] and a [hash algorithm]. The scheme decides +/// how the records in the zone will be collected, serialized, and hashed. The +/// hash algorithm simply selects a cryptographic hash function. The scheme +/// and hash algorithm are completely independent selections; at present, +/// there are no (overt or subtle) interactions hindering certain combinations +/// of scheme and hash algorithm. +/// +/// [scheme]: ZoneMDScheme +/// [hash algorithm]: ZoneMDHashAlg +/// +/// At present, [`ZoneMD`] has some drawbacks. The defined schemes do not +/// support parallelization or incrementality, so arbitrarily small changes +/// to the zone require re-computing the digest (effectively) from scratch. +/// While this is acceptable for smaller zones, it hinders usage in larger +/// zones (primarily TLDs). New algorithms may be defined in the future which +/// provide parallelization and incrementality without loss of security. +/// +/// ## Wire Format +/// +/// The wire format of a [`ZoneMD`] record is the concatenation of its fields, +/// in the same order as the `struct` definition. +/// +/// The memory layout of the [`ZoneMD`] type is identical to its serialization +/// in the wire format. This means it can be parsed from the wire format in a +/// zero-copy fashion, which is more efficient. +/// +/// ## Usage +/// +/// Because [`ZoneMD`] is a record data type, it is usually handled within +/// an enum like [`RecordData`]. This section describes how to use it +/// independently (or when building new record data from scratch). +/// +/// [`RecordData`]: crate::new::rdata::RecordData +/// +/// By default, [`ZoneMD`] is a _dynamically sized type_ (DST). It is not +/// possible to store a [`ZoneMD`] in place (e.g. in a local variable); it +/// must be held indirectly, via a reference or a smart pointer type like +/// [`Box`]. +/// +/// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html +/// +/// However, [`ZoneMD`] _can_ be constructed in place by taking advantage of +/// its generic parameter. Just as you can define a `[u8; 48]` in a local +/// variable, then hold it by reference as a `&[u8]`, you can define a +/// `ZoneMD<[u8; 48]>` in a local variable, then hold it by reference as a +/// `&ZoneMD<[u8]>`. `[u8]` is the default for that generic parameter. +/// +/// There's a few ways to build a [`ZoneMD`]: +/// +/// ``` +/// # use domain::new::base::wire::{ParseBytes, ParseBytesZC, BuildBytes}; +/// # use domain::new::rdata::{ZoneMD, ZoneMDScheme, ZoneMDHashAlg}; +/// # +/// // Construct a 'ZoneMD' directly: +/// let direct: ZoneMD<[u8; 48]> = ZoneMD { +/// serial: 42.into(), +/// scheme: ZoneMDScheme::SIMPLE, +/// hash_alg: ZoneMDHashAlg::SHA384, +/// digest: [ +/// 0xb9, 0x10, 0xcb, 0xc5, 0x64, 0xfa, 0x4d, 0x47, +/// 0x52, 0xde, 0x22, 0x31, 0x27, 0x4a, 0x42, 0xcc, +/// 0xfd, 0x3d, 0x88, 0xde, 0x1c, 0x16, 0x4b, 0xfa, +/// 0xc2, 0x61, 0x20, 0x32, 0x30, 0x01, 0x48, 0xa9, +/// 0x7e, 0x73, 0x00, 0x4a, 0x63, 0x6f, 0x0e, 0xa5, +/// 0xfc, 0x17, 0xe6, 0xbe, 0x74, 0x8f, 0x3f, 0x2a, +/// ], +/// }; +/// // Taken by reference, the generic parameter can be dropped. +/// // This is an unsizing coercion to 'ZoneMD<[u8]>'. +/// let direct: &ZoneMD = &direct; +/// +/// // Parse a 'ZoneMD' from the DNS wire format: +/// let bytes = [ +/// 0, 0, 0, 42, 1, 1, +/// 0xb9, 0x10, 0xcb, 0xc5, 0x64, 0xfa, 0x4d, 0x47, +/// 0x52, 0xde, 0x22, 0x31, 0x27, 0x4a, 0x42, 0xcc, +/// 0xfd, 0x3d, 0x88, 0xde, 0x1c, 0x16, 0x4b, 0xfa, +/// 0xc2, 0x61, 0x20, 0x32, 0x30, 0x01, 0x48, 0xa9, +/// 0x7e, 0x73, 0x00, 0x4a, 0x63, 0x6f, 0x0e, 0xa5, +/// 0xfc, 0x17, 0xe6, 0xbe, 0x74, 0x8f, 0x3f, 0x2a, +/// ]; +/// let from_bytes = ZoneMD::parse_bytes_by_ref(&bytes).unwrap(); +/// // It is also possible to use '<&ZoneMD>::parse_bytes()'. +/// # assert_eq!(from_bytes, direct); +/// +/// // Serialize a 'ZoneMD' in the DNS wire format: +/// let mut buffer = vec![0u8; from_bytes.built_bytes_size()]; +/// from_bytes.build_bytes(&mut buffer).unwrap(); +/// assert_eq!(buffer, bytes); +/// +/// // Parse a 'ZoneMD' from the wire format, but on the heap: +/// let buffer: Box<[u8]> = buffer.into_boxed_slice(); +/// let from_boxed_bytes: Box = ZoneMD::parse_bytes_in(buffer).unwrap(); +/// assert_eq!(from_bytes, &*from_boxed_bytes); +/// ``` +/// +/// [`ZoneMD`] implements [`Copy`], [`Clone`], and/or [`UnsizedCopy`] if +/// its digest type implements them. By default, its digest type is `[u8]`, +/// which only implements [`UnsizedCopy`]. A `&ZoneMD` can be copied into a +/// different container (e.g. `Box`) using [`unsized_copy_into()`]. +/// +/// [`unsized_copy_into()`]: UnsizedCopy::unsized_copy_into() +/// +/// For debugging, [`ZoneMD`] can be formatted using [`fmt::Debug`]. +/// +/// To serialize a [`ZoneMD`] in the wire format, use [`BuildBytes`] +/// (which will serialize it to a given buffer) or [`AsBytes`] (which will +/// cast the [`ZoneMD`] into a byte sequence in place). It also supports +/// [`BuildInMessage`]. +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Hash, + AsBytes, + BuildBytes, + ParseBytes, + ParseBytesZC, + UnsizedCopy, +)] +#[repr(C)] +pub struct ZoneMD { + /// The associated SOA serial number. + /// + /// The [`ZoneMD`] is specifically associated with the instance of the + /// DNS zone that has this serial number in its SOA record (i.e. in + /// [`Soa::serial`]). When performing ZONEMD verification, this field + /// must be checked for consistency with the actual SOA record. + /// + /// [`Soa::serial`]: crate::new::rdata::Soa::serial + /// + /// In case a ZONEMD verification failure occurs, an inconsistency in this + /// field indicates that the ZONEMD record might simply be out-of-date. + /// This can be used for diagnostics, but must not be used to infer + /// anything about the integrity or authenticity of the zone. + pub serial: Serial, + + /// The scheme used to compute the digest. + /// + /// This field "identifies the methods by which data is collated and + /// presented as input to the hashing function". It is independent of + /// the hash algorithm, which is specified separately. + pub scheme: ZoneMDScheme, + + /// The hash algorithm used. + /// + /// This field "identifies the cryptographic hash algorithm used to + /// construct the digest". It is independent of the scheme, which dictates + /// how the hash algorithm is used, and is specified separately. + pub hash_alg: ZoneMDHashAlg, + + /// The digest. + /// + /// This field stores the digest, as computed by the specified scheme and + /// hash algorithm. While it is dictated by a generic parameter, it should + /// almost always be `[u8]` or `[u8; N]` for some hard-coded size. This + /// genericity can help construct it. + /// + /// The digest is required to be 12 bytes or more in size, but it is + /// generally not advisable to truncate cryptographic hash functions. + pub digest: Digest, +} + +//--- Formatting + +impl> fmt::Debug for ZoneMD { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + struct DigestFmt<'a>(&'a [u8]); + + impl fmt::Debug for DigestFmt<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut first = true; + for chunk in self.0.chunks(2) { + if !first { + f.write_str(" ")?; + } + first = false; + for &c in chunk { + write!(f, "{c:02x}")?; + } + } + Ok(()) + } + } + + f.debug_struct("ZoneMD") + .field("serial", &self.serial) + .field("scheme", &self.scheme) + .field("hash_alg", &self.hash_alg) + .field("digest", &DigestFmt(self.digest.as_ref())) + .finish() + } +} + +//--- Cloning + +// The following impl would be ideal, but it conflicts with +// 'impl Clone for Box'. +// +//impl Clone for Box> { ... } +// +// The common case is 'ZoneMD<[u8]>' (i.e. just 'ZoneMD'), so we only +// implement 'Clone' for that. +#[cfg(feature = "alloc")] +impl Clone for alloc::boxed::Box> { + fn clone(&self) -> Self { + (*self).unsized_copy_into() + } +} + +//--- Canonical operations + +impl CanonicalRecordData + for ZoneMD +{ + fn cmp_canonical(&self, other: &Self) -> Ordering { + u32::from(self.serial) + .cmp(&other.serial.into()) + .then(self.scheme.cmp(&other.scheme)) + .then(self.hash_alg.cmp(&other.hash_alg)) + .then_with(|| self.digest.cmp(&other.digest)) + } +} + +//--- Parsing record data + +impl<'a, Digest: ?Sized + ParseBytesZC> ParseRecordData<'a> + for &'a ZoneMD +{ +} + +impl<'a, Digest: ?Sized + ParseBytesZC> ParseRecordDataBytes<'a> + for &'a ZoneMD +{ + fn parse_record_data_bytes( + bytes: &'a [u8], + rtype: RType, + ) -> Result { + match rtype { + RType::ZONEMD => ZoneMD::parse_bytes_by_ref(bytes), + _ => Err(ParseError), + } + } +} + +//--- Building into DNS messages + +impl BuildInMessage for ZoneMD { + fn build_in_message( + &self, + contents: &mut [u8], + start: usize, + _compressor: &mut NameCompressor, + ) -> Result { + let bytes = contents.get_mut(start..).ok_or(TruncationError)?; + let rest_len = self.build_bytes(bytes)?.len(); + Ok(contents.len() - rest_len) + } +} + +//----------- ZoneMDScheme --------------------------------------------------- + +/// A scheme for computing [`ZoneMD`] digests. +/// +/// This enumeration describes the [`ZoneMD::scheme`] field. It is specified +/// by [RFC 8976, section 2.2.2]. IANA maintains [a registry][iana] of defined +/// schemes. +/// +/// [RFC 8976, section 2.2.2]: https://www.rfc-editor.org/rfc/rfc8976.html#section-2.2.2 +/// [iana]: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#zonemd-schemes +/// +/// Scheme values 240-254 (inclusive) are allocated for "Private Use". Scheme +/// values 0 and 255 are "Reserved". +#[derive( + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + AsBytes, + BuildBytes, + ParseBytes, + ParseBytesZC, + SplitBytes, + SplitBytesZC, + UnsizedCopy, +)] +#[repr(transparent)] +pub struct ZoneMDScheme { + /// The scheme code. + pub code: u8, +} + +//--- Associated Constants + +impl ZoneMDScheme { + /// The SIMPLE scheme. + /// + /// SIMPLE is, as expected, a simple scheme for computing the ZONEMD + /// digest. It is specified by [RFC 8976, section 3.3.1]. At present, + /// implementations are required to support it. + /// + /// [RFC 8976, section 3.3.1]: https://www.rfc-editor.org/rfc/rfc8976.html#section-3.3.1 + /// + /// SIMPLE includes glue records and occluded data in the zone, sorts it + /// in DNSSEC canonical order, and passes the entire zone (i.e. records + /// serialized in the DNSSEC canonical wire format, concatenated together) + /// into a single invocation of the hash function. + pub const SIMPLE: Self = Self { code: 1 }; +} + +//--- Formatting + +impl fmt::Debug for ZoneMDScheme { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match *self { + Self::SIMPLE => "ZoneMDScheme::SIMPLE", + _ => return write!(f, "ZoneMDScheme({})", self.code), + }) + } +} + +//----------- ZoneMDHashAlg -------------------------------------------------- + +/// A hash algorithm for computing [`ZoneMD`] digests. +/// +/// This enumeration describes the [`ZoneMD::hash_alg`] field. It is specified +/// by [RFC 8976, section 2.2.3]. IANA maintains [a registry][iana] of defined +/// hash algorithms. +/// +/// [RFC 8976, section 2.2.3]: https://www.rfc-editor.org/rfc/rfc8976.html#section-2.2.3 +/// [iana]: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#zonemd-hash-algorithms +/// +/// Algorithm values 240-254 (inclusive) are allocated for "Private Use". +/// Algorithm values 0 and 255 are "Reserved". +#[derive( + Copy, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + AsBytes, + BuildBytes, + ParseBytes, + ParseBytesZC, + SplitBytes, + SplitBytesZC, + UnsizedCopy, +)] +#[repr(transparent)] +pub struct ZoneMDHashAlg { + /// The algorithm code. + pub code: u8, +} + +//--- Associated Constants + +impl ZoneMDHashAlg { + /// The SHA384 algorithm. + /// + /// The resulting digest is 48 bytes in size, and must not be truncated. + /// At present, implementations are required to support it. + pub const SHA384: Self = Self { code: 1 }; + + /// The SHA512 algorithm. + /// + /// The resulting digest is 64 bytes in size, and must not be truncated. + /// At present, implementations are recommended to support it. + pub const SHA512: Self = Self { code: 2 }; +} + +//--- Formatting + +impl fmt::Debug for ZoneMDHashAlg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match *self { + Self::SHA384 => "ZoneMDHashAlg::SHA384", + Self::SHA512 => "ZoneMDHashAlg::SHA512", + _ => return write!(f, "ZoneMDHashAlg({})", self.code), + }) + } +} From 868398a4092f3c2065705e52a771377fb8cdb167 Mon Sep 17 00:00:00 2001 From: arya dradjica Date: Fri, 20 Feb 2026 12:58:20 +0100 Subject: [PATCH 3/6] [new] Use one-space periods in docs for consistency --- src/new/base/build/message.rs | 12 ++--- src/new/base/build/mod.rs | 10 ++-- src/new/base/charstr.rs | 6 +-- src/new/base/message.rs | 30 ++++++------ src/new/base/mod.rs | 42 ++++++++--------- src/new/base/name/absolute.rs | 28 +++++------ src/new/base/name/compressor.rs | 74 +++++++++++++++--------------- src/new/base/name/label.rs | 16 +++---- src/new/base/name/mod.rs | 30 ++++++------ src/new/base/name/reversed.rs | 22 ++++----- src/new/base/name/unparsed.rs | 6 +-- src/new/base/parse/mod.rs | 32 ++++++------- src/new/base/serial.rs | 2 +- src/new/base/wire/build.rs | 10 ++-- src/new/base/wire/mod.rs | 14 +++--- src/new/base/wire/parse.rs | 40 ++++++++-------- src/new/base/wire/size_prefixed.rs | 22 ++++----- src/new/edns/cookie.rs | 8 ++-- src/new/edns/mod.rs | 4 +- src/new/mod.rs | 20 ++++---- src/new/rdata/basic/a.rs | 10 ++-- src/new/rdata/basic/cname.rs | 20 ++++---- src/new/rdata/basic/hinfo.rs | 24 +++++----- src/new/rdata/basic/mx.rs | 18 ++++---- src/new/rdata/basic/ns.rs | 20 ++++---- src/new/rdata/basic/ptr.rs | 20 ++++---- src/new/rdata/basic/soa.rs | 48 +++++++++---------- src/new/rdata/basic/txt.rs | 24 +++++----- src/new/rdata/dname.rs | 24 +++++----- src/new/rdata/dnssec/nsec.rs | 2 +- src/new/rdata/edns.rs | 26 +++++------ src/new/rdata/ipv6.rs | 12 ++--- src/new/rdata/mod.rs | 38 +++++++-------- 33 files changed, 357 insertions(+), 357 deletions(-) diff --git a/src/new/base/build/message.rs b/src/new/base/build/message.rs index 2cddc9122..fb6899953 100644 --- a/src/new/base/build/message.rs +++ b/src/new/base/build/message.rs @@ -86,7 +86,7 @@ impl MessageBuilder<'_, '_> { /// The message built thus far, mutably. /// /// Compressed names in the message must not be modified here, as the name - /// compressor relies on them. Modifying them will break name compression + /// compressor relies on them. Modifying them will break name compression /// and result in misformatted messages. #[must_use] pub fn message_mut(&mut self) -> &mut Message { @@ -123,7 +123,7 @@ impl<'b> MessageBuilder<'b, '_> { /// /// The message will not be allowed to exceed the given size, in bytes. /// Only the message header and contents are counted; the enclosing UDP - /// or TCP packet size is not considered. If the message already exceeds + /// or TCP packet size is not considered. If the message already exceeds /// this size, a [`TruncationError`] is returned. pub fn limit_to(&mut self, size: usize) -> Result<(), TruncationError> { if 12 + self.offset <= size { @@ -154,7 +154,7 @@ impl<'b> MessageBuilder<'b, '_> { /// ## Errors /// /// If the item cannot be appended (because it needs to come before items - /// already in the message), [`Misplaced`] is returned. If the item does + /// already in the message), [`Misplaced`] is returned. If the item does /// not fit in the message buffer, [`Truncated`] is returned. /// /// [`Misplaced`]: MessageBuildError::Misplaced @@ -203,7 +203,7 @@ impl<'b> MessageBuilder<'b, '_> { /// ## Errors /// /// If the item cannot be appended (because it needs to come before items - /// already in the message), [`Misplaced`] is returned. If the item does + /// already in the message), [`Misplaced`] is returned. If the item does /// not fit in the message buffer, [`Truncated`] is returned. /// /// [`Misplaced`]: MessageBuildError::Misplaced @@ -221,7 +221,7 @@ impl<'b> MessageBuilder<'b, '_> { /// ## Errors /// /// If the item cannot be appended (because it needs to come before items - /// already in the message), [`Misplaced`] is returned. If the item does + /// already in the message), [`Misplaced`] is returned. If the item does /// not fit in the message buffer, [`Truncated`] is returned. /// /// [`Misplaced`]: MessageBuildError::Misplaced @@ -239,7 +239,7 @@ impl<'b> MessageBuilder<'b, '_> { /// ## Errors /// /// If the item cannot be appended (because it needs to come before items - /// already in the message), [`Misplaced`] is returned. If the item does + /// already in the message), [`Misplaced`] is returned. If the item does /// not fit in the message buffer, [`Truncated`] is returned. /// /// [`Misplaced`]: MessageBuildError::Misplaced diff --git a/src/new/base/build/mod.rs b/src/new/base/build/mod.rs index a445879a8..d48297afa 100644 --- a/src/new/base/build/mod.rs +++ b/src/new/base/build/mod.rs @@ -1,10 +1,10 @@ //! Building DNS messages in the wire format. //! //! The [`wire`](super::wire) module provides basic serialization capability, -//! but it is not specialized to DNS messages. This module provides that +//! but it is not specialized to DNS messages. This module provides that //! specialization within an ergonomic interface. //! -//! The core of the high-level interface is [`MessageBuilder`]. It provides +//! The core of the high-level interface is [`MessageBuilder`]. It provides //! the most intuitive methods for appending whole questions and records. //! //! ``` @@ -77,9 +77,9 @@ pub trait BuildInMessage { /// /// ## Errors /// - /// Fails if the message buffer is too small to fit the object. Parts of + /// Fails if the message buffer is too small to fit the object. Parts of /// the message buffer (anything after `start`) may have been modified, - /// but should not be considered part of the initialized message. The + /// but should not be considered part of the initialized message. The /// caller should explicitly reset the name compressor to `start` to undo /// the effects of this function. fn build_in_message( @@ -133,7 +133,7 @@ impl BuildInMessage for [T] { /// Write a sequence of elements to a DNS message. /// /// If an element cannot be written due to a truncation error, the whole - /// sequence is considered to have failed. For more nuanced behaviour on + /// sequence is considered to have failed. For more nuanced behaviour on /// truncation, build each element manually. fn build_in_message( &self, diff --git a/src/new/base/charstr.rs b/src/new/base/charstr.rs index c9cfc3721..f28fb4617 100644 --- a/src/new/base/charstr.rs +++ b/src/new/base/charstr.rs @@ -22,7 +22,7 @@ use super::{ pub struct CharStr { /// The underlying octets. /// - /// This is at most 255 bytes. It does not include the length octet that + /// This is at most 255 bytes. It does not include the length octet that /// precedes the character string when serialized in the wire format. pub octets: [u8], } @@ -273,7 +273,7 @@ impl CharStrBuf { pub fn wire_bytes(&self) -> &[u8] { let ptr = self as *const _ as *const u8; let len = self.len() + 1; - // SAFETY: 'Self' is 'repr(C)' and contains no padding. It can be + // SAFETY: 'Self' is 'repr(C)' and contains no padding. It can be // interpreted as a 256-byte array. unsafe { core::slice::from_raw_parts(ptr, len) } } @@ -430,7 +430,7 @@ impl fmt::Debug for CharStrBuf { /// An error in parsing a [`CharStr`] from a string. /// -/// This can be returned by [`CharStrBuf::from_str()`]. It is not used when +/// This can be returned by [`CharStrBuf::from_str()`]. It is not used when /// parsing character strings from the zonefile format, which uses a different /// mechanism. #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/new/base/message.rs b/src/new/base/message.rs index 91043b040..76db6438b 100644 --- a/src/new/base/message.rs +++ b/src/new/base/message.rs @@ -86,11 +86,11 @@ impl Message { /// # Safety /// /// This method uses `pointer::offset()`: `self` must be "derived from a - /// pointer to some allocated object". There must be at least 12 bytes - /// between `self` and the end of that allocated object. A reference to + /// pointer to some allocated object". There must be at least 12 bytes + /// between `self` and the end of that allocated object. A reference to /// `Message` will always result in a pointer satisfying this. pub unsafe fn truncate_ptr(this: *mut Message, size: usize) -> *mut Self { - // Extract the metadata from 'this'. We know it's slice metadata. + // Extract the metadata from 'this'. We know it's slice metadata. // // SAFETY: '[()]' is a zero-sized type and references to it can be // created from arbitrary pointers, since every pointer is valid for @@ -160,7 +160,7 @@ impl fmt::Display for Header { /// /// This 16-bit field provides information about the containing DNS message. /// Its contents define the purpose of the message, e.g. whether it is a query -/// or a response. Due to its small size, it doesn't cover everything; the +/// or a response. Due to its small size, it doesn't cover everything; the /// OPT record may provide additional information, if it is present. /// /// # Specification @@ -168,11 +168,11 @@ impl fmt::Display for Header { // TODO: Update regularly. // /// The header field has been updated by several RFCs and the interpretation -/// of its bits has changed in some places. The following is a collection of +/// of its bits has changed in some places. The following is a collection of /// the relevant RFC notes; it is up-to-date as of *2025-04-03*. /// /// The descriptions here are specific to the `QUERY` opcode, which is by far -/// the most common. Other opcodes can change the interpretation of the bits +/// the most common. Other opcodes can change the interpretation of the bits /// here. /// /// ```text @@ -201,8 +201,8 @@ impl fmt::Display for Header { /// /// - `TC`: whether the response is truncated (due to channel limitations). /// -/// Specified by [RFC 1035, section 4.1.1]. Behaviour clarified by [RFC -/// 2181, section 9]. Behaviour for DNSSEC servers specified by [RFC 4035, +/// Specified by [RFC 1035, section 4.1.1]. Behaviour clarified by [RFC +/// 2181, section 9]. Behaviour for DNSSEC servers specified by [RFC 4035, /// section 3.1]. /// /// - `RD`: whether the DNS client wishes for a recursively resolved answer. @@ -215,16 +215,16 @@ impl fmt::Display for Header { /// /// - `AD`: whether the DNS server has authenticated the answer. /// -/// Defined by [RFC 2535, section 6.1]. Behaviour for authoritative name -/// servers specified by [RFC 4035, section 3.1.6]. Behaviour for recursive +/// Defined by [RFC 2535, section 6.1]. Behaviour for authoritative name +/// servers specified by [RFC 4035, section 3.1.6]. Behaviour for recursive /// name servers specified by [RFC 4035, section 3.2.3] and updated by [RFC -/// 6840, section 5.8]. Behaviour for DNS clients specified by [RFC 6840, +/// 6840, section 5.8]. Behaviour for DNS clients specified by [RFC 6840, /// section 5.7]. /// /// - `CD`: whether the DNS server should avoid authenticating the answer. /// -/// Defined by [RFC 2535, section 6.1]. Behaviour for authoritative name -/// servers specified by [RFC 4035, section 3.1.6]. Behaviour for recursive +/// Defined by [RFC 2535, section 6.1]. Behaviour for authoritative name +/// servers specified by [RFC 4035, section 3.1.6]. Behaviour for recursive /// name servers specified by [RFC 4035, section 3.2.2] and updated by [RFC /// 6840, section 5.9]. /// @@ -516,7 +516,7 @@ impl fmt::Display for SectionCounts { /// A question or a record. /// /// This is useful for building and parsing the contents of a [`Message`] -/// ergonomically and efficiently. An iterator of [`MessageItem`]s can be +/// ergonomically and efficiently. An iterator of [`MessageItem`]s can be /// retrieved using [`Message::parse()`]. #[derive(Clone, Debug)] pub enum MessageItem { @@ -536,7 +536,7 @@ pub enum MessageItem { /// An EDNS record. /// - /// This is a record in the additional section. It uses a distinct type + /// This is a record in the additional section. It uses a distinct type /// as the class and TTL fields of the record are interpreted differently. Edns(EdnsRecord), } diff --git a/src/new/base/mod.rs b/src/new/base/mod.rs index f74299135..63a62ddaf 100644 --- a/src/new/base/mod.rs +++ b/src/new/base/mod.rs @@ -1,26 +1,26 @@ //! Basic DNS. //! //! This module provides the essential types and functionality for working -//! with DNS. In particular, it allows building and parsing DNS messages to +//! with DNS. In particular, it allows building and parsing DNS messages to //! and from the wire format. //! -//! This provides a mid-level and low-level API. It guides users towards the +//! This provides a mid-level and low-level API. It guides users towards the //! most efficient solutions for their needs, and (where necessary) provides //! fallbacks that trade efficiency for flexibility and/or ergonomics. //! //! # A quick reference on types //! -//! [`Message`] is the top-level type, representing a whole DNS message. It +//! [`Message`] is the top-level type, representing a whole DNS message. It //! stores data in the wire format, making it trivial to parse into or build -//! from. It can provide direct access to the message [`Header`], and the +//! from. It can provide direct access to the message [`Header`], and the //! questions and records within it (collectively called [`MessageItem`]s) can //! be parsed/traversed using [`Message::parse()`]. //! //! [`Question`] and [`Record`] are exactly what they look like, and are -//! simple `struct`s so they can be constructed and inspected easily. They +//! simple `struct`s so they can be constructed and inspected easily. They //! are generic over a _domain name type_ (discussed below), which you will -//! need to pick explicitly. [`Record`] is also generic over the record data -//! type; you probably want [`new::rdata::RecordData`]. See the documentation +//! need to pick explicitly. [`Record`] is also generic over the record data +//! type; you probably want [`new::rdata::RecordData`]. See the documentation //! on [`Record`] and [`new::rdata`] for more information. //! //! [`new::rdata`]: crate::new::rdata @@ -28,10 +28,10 @@ //! //! The [`name`] module provides various types that represent domain //! names, and describes the situations each type is most appropriate -//! for. As a quick summary: try to use [`RevNameBuf`] by default, or +//! for. As a quick summary: try to use [`RevNameBuf`] by default, or //! Box<[RevName]> if lots of domain names need to be -//! stored. If DNSSEC canonical ordering is necessary, use [`NameBuf`] or -//! Box<[Name]> respectively. There are more efficient +//! stored. If DNSSEC canonical ordering is necessary, use [`NameBuf`] or +//! Box<[Name]> respectively. There are more efficient //! alternatives in some cases; see [`name`]. //! //! [Name]: name::Name @@ -42,8 +42,8 @@ //! # Parsing DNS messages //! //! The [`parse`] module provides mid-level and low-level APIs for parsing -//! DNS messages from the wire format. To parse the questions and records in -//! a [`Message`], use [`Message::parse()`]. To parse a message (including +//! DNS messages from the wire format. To parse the questions and records in +//! a [`Message`], use [`Message::parse()`]. To parse a message (including //! questions and records) from bytes, use [`MessageParser::new()`]. //! //! [`MessageParser::new()`]: parse::MessageParser::new() @@ -103,8 +103,8 @@ //! # Building DNS messages //! //! The [`build`] module provides mid-level and low-level APIs for building -//! DNS messages in the wire format. [`MessageBuilder`] is the primary entry -//! point; it writes into a user-provided byte buffer. To begin building a +//! DNS messages in the wire format. [`MessageBuilder`] is the primary entry +//! point; it writes into a user-provided byte buffer. To begin building a //! DNS message, use [`MessageBuilder::new()`]. //! //! [`MessageBuilder`]: build::MessageBuilder @@ -152,23 +152,23 @@ //! //! Because many elements of DNS messages have variable-length encodings in //! the wire format, this module relies on Rust's language support for -//! _dynamically sized types_ (DSTs) to represent them. The top-level +//! _dynamically sized types_ (DSTs) to represent them. The top-level //! [`Message`] type, [`CharStr`], [`Name`], etc. are all DSTs. //! //! [`Name`]: name::Name //! //! DSTs cannot be passed around by value because the compiler needs to know -//! (at compile-time) how much stack space to allocate for them. As such, a +//! (at compile-time) how much stack space to allocate for them. As such, a //! DST has to be held indirectly, by reference or in a container like -//! [`Box`]. The former work well in "short-term" contexts (e.g. within a +//! [`Box`]. The former work well in "short-term" contexts (e.g. within a //! function), while the latter are necessary in long-term contexts. //! //! [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html //! //! Container types that implement [`UnsizedCopyFrom`] automatically work with -//! any [`UnsizedCopy`] types. This trait allows DSTs to be copied into such +//! any [`UnsizedCopy`] types. This trait allows DSTs to be copied into such //! container types, which is especially useful to store a DST for long-term -//! use. It is already implemented for [`Box`], [`Arc`], [`Vec`], etc., and +//! use. It is already implemented for [`Box`], [`Arc`], [`Vec`], etc., and //! users can implement it on their own container types too. //! //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html @@ -214,8 +214,8 @@ pub mod wire; /// A compatibility module with [`domain::base`]. /// /// This re-exports a large part of the `new::base` API surface using the same -/// import paths as the old `base` module. It is a stopgap measure to help -/// users port existing code over to `new::base`. Every export comes with a +/// import paths as the old `base` module. It is a stopgap measure to help +/// users port existing code over to `new::base`. Every export comes with a /// deprecation message to help users switch to the right tools. pub mod compat { #![allow(deprecated)] diff --git a/src/new/base/name/absolute.rs b/src/new/base/name/absolute.rs index 3fb900ef3..32163aa61 100644 --- a/src/new/base/name/absolute.rs +++ b/src/new/base/name/absolute.rs @@ -203,7 +203,7 @@ impl Clone for alloc::boxed::Box { impl PartialEq for Name { fn eq(&self, other: &Self) -> bool { - // Instead of iterating labels, blindly iterate bytes. The locations + // Instead of iterating labels, blindly iterate bytes. The locations // of labels don't matter since we're testing everything for equality. // NOTE: Label lengths (which are less than 64) aren't affected by @@ -230,21 +230,21 @@ impl Ord for Name { fn cmp(&self, that: &Self) -> Ordering { // We wish to compare the labels in these names in reverse order. // Unfortunately, labels in absolute names cannot be traversed - // backwards efficiently. We need to try harder. + // backwards efficiently. We need to try harder. // - // Consider two names that are not equal. This means that one name is + // Consider two names that are not equal. This means that one name is // a strict suffix of the other, or that the two had different labels - // at some position. Following this mismatched label is a suffix of + // at some position. Following this mismatched label is a suffix of // labels that both names do agree on. // // We traverse the bytes in the names in reverse order and find the - // length of their shared suffix. The actual shared suffix, in units + // length of their shared suffix. The actual shared suffix, in units // of labels, may be shorter than this (because the last bytes of the // mismatched labels could be the same). // // Then, we traverse the labels of both names in forward order, until - // we hit the shared suffix territory. We try to match up the names - // in order to discover the real shared suffix. Once the suffix is + // we hit the shared suffix territory. We try to match up the names + // in order to discover the real shared suffix. Once the suffix is // found, the immediately preceding label (if there is one) contains // the inequality, and can be compared as usual. @@ -256,7 +256,7 @@ impl Ord for Name { let Some(suffix_len) = suffix_len else { // 'iter::zip()' simply ignores unequal iterators, stopping when - // either iterator finishes. Even though the two names had no + // either iterator finishes. Even though the two names had no // mismatching bytes, one could be longer than the other. return self.len().cmp(&that.len()); }; @@ -274,7 +274,7 @@ impl Ord for Name { let (llen, rlen) = (lhs.remaining().len(), rhs.remaining().len()); if llen == rlen && llen <= suffix_len { // We're in shared suffix territory, and 'lhs' and 'rhs' have - // the same length. Thus, they must be identical, and we have + // the same length. Thus, they must be identical, and we have // found the shared suffix. break prev.0.cmp(prev.1); } else if llen > rlen { @@ -400,11 +400,11 @@ impl<'a> SplitMessageBytes<'a> for NameBuf { contents: &'a [u8], start: usize, ) -> Result<(Self, usize), ParseError> { - // NOTE: The input may be controlled by an attacker. Compression + // NOTE: The input may be controlled by an attacker. Compression // pointers can be arranged to cause loops or to access every byte in - // the message in random order. Instead of performing complex loop + // the message in random order. Instead of performing complex loop // detection, which would probably perform allocations, we simply - // disallow a name to point to data _after_ it. Standard name + // disallow a name to point to data _after_ it. Standard name // compressors will never generate such pointers. let mut buffer = Self::empty(); @@ -443,7 +443,7 @@ impl<'a> ParseMessageBytes<'a> for NameBuf { contents: &'a [u8], start: usize, ) -> Result { - // See 'split_from_message()' for details. The only differences are + // See 'split_from_message()' for details. The only differences are // in the range of the first iteration, and the check that the first // iteration exactly covers the input range. @@ -831,7 +831,7 @@ impl<'a> serde::Deserialize<'a> for std::boxed::Box { /// An error in parsing a [`Name`] from a string. /// -/// This can be returned by [`NameBuf::from_str()`]. It is not used when +/// This can be returned by [`NameBuf::from_str()`]. It is not used when /// parsing names from the zonefile format, which uses a different mechanism. #[derive(Clone, Debug, PartialEq, Eq)] pub enum NameParseError { diff --git a/src/new/base/name/compressor.rs b/src/new/base/name/compressor.rs index d87cc8db1..22647c425 100644 --- a/src/new/base/name/compressor.rs +++ b/src/new/base/name/compressor.rs @@ -7,15 +7,15 @@ use super::{Name, RevName}; /// A domain name compressor. /// /// This struct provides name compression functionality when building DNS -/// messages. It compares domain names to those already in the message, and +/// messages. It compares domain names to those already in the message, and /// if a shared suffix is found, the newly-inserted name will point at the /// existing instance of the suffix. /// /// This struct stores the positions of domain names already present in the /// DNS message, as it is otherwise impossible to differentiate domain names -/// from other bytes. Only recently-inserted domain names are stored, and +/// from other bytes. Only recently-inserted domain names are stored, and /// only from the first 16KiB of the message (as compressed names cannot point -/// any further). This is good enough for building small and large messages. +/// any further). This is good enough for building small and large messages. #[repr(align(64))] // align to a typical cache line pub struct NameCompressor { /// The last use position of every entry. @@ -26,12 +26,12 @@ pub struct NameCompressor { /// The last use position is calculated somewhat approximately; it would /// most appropriately be '(number of children, position of inserted /// name)', but it is approximated as 'position of inserted name + offset - /// into the name if it were uncompressed'. In either formula, the entry + /// into the name if it were uncompressed'. In either formula, the entry /// with the minimum value would be evicted first. /// /// Both formulae guarantee that entries will be evicted before any of - /// their dependencies. The former formula requires at least 19 bits of - /// storage, while the latter requires less than 15 bits. The latter can + /// their dependencies. The former formula requires at least 19 bits of + /// storage, while the latter requires less than 15 bits. The latter can /// prioritize a deeply-nested name suffix over a slightly more recently /// used name that is less nested, but this should be quite rare. /// @@ -53,7 +53,7 @@ pub struct NameCompressor { /// The length of the relative domain name in each entry. /// /// This is the length of the domain name each entry represents, up to - /// (but excluding) the root label or compression pointer. It is used to + /// (but excluding) the root label or compression pointer. It is used to /// quickly find the end of the domain name for matching suffixes. /// /// Valid values: @@ -75,7 +75,7 @@ pub struct NameCompressor { /// A 16-bit hash of the entry's last label. /// /// An existing entry will be used for compressing a new domain name when - /// the last label in both of them is identical. This field stores a hash + /// the last label in both of them is identical. This field stores a hash /// over the last label in every entry, to speed up lookups. /// /// Valid values: @@ -102,14 +102,14 @@ impl NameCompressor { /// write a [`RevName`] into a DNS message. /// /// Given the contents of the DNS message, determine how to compress the - /// given domain name. If a suitable compression for the name could be + /// given domain name. If a suitable compression for the name could be /// found, this function returns the length of the uncompressed suffix as /// well as the address of the compressed prefix. /// /// The contents slice should begin immediately after the 12-byte message - /// header. It must end at the position the name will be inserted. It is + /// header. It must end at the position the name will be inserted. It is /// assumed that the domain names inserted in these contents still exist - /// from previous calls to [`compress_name()`] and related methods. If + /// from previous calls to [`compress_name()`] and related methods. If /// this is not true, panics or silently invalid results may occur. /// /// The compressor's state will be updated to assume the provided name was @@ -199,7 +199,7 @@ impl NameCompressor { // Search for an entry with a matching hash and parent. for i in 0..32 { - // Check the hash first, as it's less likely to match. It's also + // Check the hash first, as it's less likely to match. It's also // okay if both checks are performed unconditionally. if self.hash[i] != hash || self.parent[i] != parent { continue; @@ -213,10 +213,10 @@ impl NameCompressor { // Find a shared suffix between the entry and the name. // - // Comparing a 'Name' to a 'RevName' properly is difficult. We're + // Comparing a 'Name' to a 'RevName' properly is difficult. We're // just going for the lazy and not-pedantically-correct version, // where we blindly match 'RevName' labels against the end of the - // 'Name'. The bytes are definitely correct, but there's a small + // 'Name'. The bytes are definitely correct, but there's a small // chance that we aren't consistent with label boundaries. // TODO(1.80): Use 'slice::split_at_checked()'. @@ -239,7 +239,7 @@ impl NameCompressor { } // Suffixes from 'entry' that were also in 'name' have been - // removed. The remainder of 'entry' does not match with 'name'. + // removed. The remainder of 'entry' does not match with 'name'. // 'name' can be compressed using this entry. let rest = name_labels.remaining(); let pos = pos + entry.len(); @@ -255,14 +255,14 @@ impl NameCompressor { /// write a [`Name`] into a DNS message. /// /// Given the contents of the DNS message, determine how to compress the - /// given domain name. If a suitable compression for the name could be + /// given domain name. If a suitable compression for the name could be /// found, this function returns the length of the uncompressed prefix as /// well as the address of the suffix. /// /// The contents slice should begin immediately after the 12-byte message - /// header. It must end at the position the name will be inserted. It is + /// header. It must end at the position the name will be inserted. It is /// assumed that the domain names inserted in these contents still exist - /// from previous calls to [`compress_name()`] and related methods. If + /// from previous calls to [`compress_name()`] and related methods. If /// this is not true, panics or silently invalid results may occur. /// /// The compressor's state will be updated to assume the provided name was @@ -305,7 +305,7 @@ impl NameCompressor { } // If there is a non-empty uncompressed prefix, register it as a new - // entry here. We already know what the hash of its last label is. + // entry here. We already know what the hash of its last label is. if !name.is_empty() && contents.len() < 16384 { // Pick the entry that was least recently used (or uninitialized). // @@ -347,7 +347,7 @@ impl NameCompressor { // Search for an entry with a matching hash and parent. for i in 0..32 { - // Check the hash first, as it's less likely to match. It's also + // Check the hash first, as it's less likely to match. It's also // okay if both checks are performed unconditionally. if self.hash[i] != hash || self.parent[i] != parent { continue; @@ -362,7 +362,7 @@ impl NameCompressor { // Find a shared suffix between the entry and the name. // // We're going to use a not-pendantically-correct implementation - // where we blindly match the ends of the names. The bytes are + // where we blindly match the ends of the names. The bytes are // definitely correct, but there's a small chance we aren't // consistent with label boundaries. @@ -374,20 +374,20 @@ impl NameCompressor { let Some(suffix_len) = suffix_len else { // 'iter::zip()' simply ignores unequal iterators, stopping - // when either iterator finishes. Even though the two names + // when either iterator finishes. Even though the two names // had no mismatching bytes, one could be longer than the // other. if name.len() > entry.len() { - // 'entry' is a proper suffix of 'name'. 'name' can be + // 'entry' is a proper suffix of 'name'. 'name' can be // compressed using 'entry', and will have at least one - // more label before it. This label needs to be found and + // more label before it. This label needs to be found and // hashed. let rest = &name[..name.len() - entry.len()]; let hash = Self::hash_label(Self::last_label(rest)); return Some((i as u8, rest, hash, pos as u16)); } else { - // 'name' is a suffix of 'entry'. 'name' can be + // 'name' is a suffix of 'entry'. 'name' can be // compressed using 'entry', and no labels will be left. let rest = &name[..0]; let hash = 0u16; @@ -419,9 +419,9 @@ impl NameCompressor { } // 'entry' and 'name' share zero or more labels, and this shared - // suffix is equal to 'name_labels'. The 'name_label' bytes might + // suffix is equal to 'name_labels'. The 'name_label' bytes might // not lie on the correct label boundaries in 'entry', but this is - // not problematic. If 'name_labels' is non-empty, 'name' can be + // not problematic. If 'name_labels' is non-empty, 'name' can be // compressed using this entry. let suffix_len = name_labels.remaining().len(); @@ -443,19 +443,19 @@ impl NameCompressor { /// The name must be a valid non-empty sequence of labels. fn last_label(name: &[u8]) -> &Label { // The last label begins with a length octet and is followed by - // the corresponding number of bytes. While the length octet + // the corresponding number of bytes. While the length octet // could look like a valid ASCII character, it would have to be // 45 (ASCII '-') or above; most labels are not that long. // // We will search backwards for a byte that could be the length - // octet of the last label. It is highly likely that exactly one + // octet of the last label. It is highly likely that exactly one // match will be found; this is guaranteed to be the right result. // If more than one match is found, we will fall back to searching // from the beginning. // // It is possible (although unlikely) for LLVM to vectorize this // process, since it performs 64 unconditional byte comparisons - // over a fixed array. A manually vectorized implementation would + // over a fixed array. A manually vectorized implementation would // generate a 64-byte mask for the valid bytes in 'name', load all // 64 bytes blindly, then do a masked comparison against iota. @@ -496,7 +496,7 @@ impl NameCompressor { /// Hash a label. fn hash_label(label: &Label) -> u16 { // This code is copied from the 'hash_bytes()' function of - // 'rustc-hash' v2.1.1, with helpers. The codebase is dual-licensed + // 'rustc-hash' v2.1.1, with helpers. The codebase is dual-licensed // under Apache-2.0 and MIT, with no explicit copyright statement. // // 'hash_bytes()' is described as "a wyhash-inspired @@ -511,19 +511,19 @@ impl NameCompressor { // Source: // // In order to hash case-insensitively, we aggressively transform the - // input bytes. We cause some collisions, but only in characters we - // don't expect to see in domain names. We do this by mapping bytes - // from 'XX0X_XXXX' to 'XX1X_XXXX'. A full list of effects: + // input bytes. We cause some collisions, but only in characters we + // don't expect to see in domain names. We do this by mapping bytes + // from 'XX0X_XXXX' to 'XX1X_XXXX'. A full list of effects: // - // - Control characters (0x00..0x20) become symbols and digits. We + // - Control characters (0x00..0x20) become symbols and digits. We // weren't expecting any control characters to appear anyway. // // - Uppercase ASCII characters become lowercased. // - // - '@[\]^_' become '`{|}~' and DEL. Underscores can occur, but DEL + // - '@[\]^_' become '`{|}~' and DEL. Underscores can occur, but DEL // is not expected, so the collision is not problematic. // - // - Half of the non-ASCII space gets folded. Unicode sequences get + // - Half of the non-ASCII space gets folded. Unicode sequences get // mapped into ASCII using Punycode, so the chance of a non-ASCII // character here is very low. diff --git a/src/new/base/name/label.rs b/src/new/base/name/label.rs index ef4990935..7d9bf2849 100644 --- a/src/new/base/name/label.rs +++ b/src/new/base/name/label.rs @@ -224,8 +224,8 @@ impl PartialOrd for Label { /// Determine the order between labels. /// /// Any uppercase ASCII characters in the labels are treated as if they - /// were lowercase. The first unequal byte between two labels determines - /// its ordering: the label with the smaller byte value is the lesser. If + /// were lowercase. The first unequal byte between two labels determines + /// its ordering: the label with the smaller byte value is the lesser. If /// two labels have all the same bytes, the shorter label is lesser; if /// they are the same length, they are equal. fn partial_cmp(&self, other: &Self) -> Option { @@ -237,8 +237,8 @@ impl Ord for Label { /// Determine the order between labels. /// /// Any uppercase ASCII characters in the labels are treated as if they - /// were lowercase. The first unequal byte between two labels determines - /// its ordering: the label with the smaller byte value is the lesser. If + /// were lowercase. The first unequal byte between two labels determines + /// its ordering: the label with the smaller byte value is the lesser. If /// two labels have all the same bytes, the shorter label is lesser; if /// they are the same length, they are equal. fn cmp(&self, other: &Self) -> Ordering { @@ -253,12 +253,12 @@ impl Ord for Label { impl Hash for Label { /// Hash this label. /// - /// All uppercase ASCII characters are lowercased beforehand. This way, + /// All uppercase ASCII characters are lowercased beforehand. This way, /// the hash of a label is case-independent, consistent with how labels /// are compared and ordered. /// /// The label is hashed as if it were a name containing a single label -- - /// the length octet is thus included. This makes the hashing consistent + /// the length octet is thus included. This makes the hashing consistent /// between names and tuples (not slices!) of labels. fn hash(&self, state: &mut H) { for &byte in self.as_bytes() { @@ -765,7 +765,7 @@ impl fmt::Debug for LabelIter<'_> { /// An error in parsing a [`Label`] from a string. /// -/// This can be returned by [`LabelBuf::from_str()`]. It is not used when +/// This can be returned by [`LabelBuf::from_str()`]. It is not used when /// parsing labels from the zonefile format, which uses a different mechanism. #[derive(Clone, Debug, PartialEq, Eq)] pub enum LabelParseError { @@ -782,7 +782,7 @@ pub enum LabelParseError { /// An invalid character was used. /// - /// Only alphanumeric characters and hyphens are allowed in labels. This + /// Only alphanumeric characters and hyphens are allowed in labels. This /// prevents the encoding of perfectly valid labels containing non-ASCII /// bytes, but they're fairly rare anyway. InvalidChar, diff --git a/src/new/base/name/mod.rs b/src/new/base/name/mod.rs index 02bc84c83..392ae0700 100644 --- a/src/new/base/name/mod.rs +++ b/src/new/base/name/mod.rs @@ -1,38 +1,38 @@ //! Domain names. //! -//! Domain names are a core concept of DNS. The whole system is essentially -//! just a mapping from domain names to arbitrary information. This module +//! Domain names are a core concept of DNS. The whole system is essentially +//! just a mapping from domain names to arbitrary information. This module //! provides types and essential functionality for working with them. //! //! A domain name is a sequence of labels, separated by ASCII periods (`.`). //! For example, `example.org.` contains three labels: `example`, `org`, and -//! `` (the root label). Outside DNS-specific code, the root label (and its +//! `` (the root label). Outside DNS-specific code, the root label (and its //! separator) are almost always omitted, but keep them in mind here. //! //! Domain names form a hierarchy, where `b.a` is the "parent" of `.c.b.a`. //! The owner of `example.org` is thus responsible for _every_ domain ending -//! with the `.example.org` suffix. The reverse order in which this hierarchy +//! with the `.example.org` suffix. The reverse order in which this hierarchy //! is expressed can sometimes be confusing. //! //! ## Domain Name Types //! //! There are several different types that can be used to represent domain -//! names. Each one is appropriate for certain situations and less useful for -//! others. Most of `domain`'s high-level APIs will hard-code domain name +//! names. Each one is appropriate for certain situations and less useful for +//! others. Most of `domain`'s high-level APIs will hard-code domain name //! types to the right options. //! -//! - [`Name`] is the standard domain name type. As is common in DNS +//! - [`Name`] is the standard domain name type. As is common in DNS //! implementations, it stores labels in the wire format from innermost to -//! outermost (i.e. `example, org` for `example.org.`). It is the right +//! outermost (i.e. `example, org` for `example.org.`). It is the right //! type to use in DNS record data. //! //! - [`RevName`] is similar to [`Name`], except that labels are stored in //! _reverse_ order, from outermost to innermost (i.e. `org, example` in -//! `example.org.`). It is the right type to use as the owner name of a +//! `example.org.`). It is the right type to use as the owner name of a //! DNS record ([`Record.rname`]). //! //! These types are _dynamically sized_; this means that they cannot be used -//! by value. The following table illustrates the various container and +//! by value. The following table illustrates the various container and //! pointer types that can be used around them, and the situations they are //! most appropriate for. //! @@ -73,13 +73,13 @@ pub use compressor::NameCompressor; /// different ways: they can be serialized into byte sequences or compared. /// /// - In record data, they are serialized following the regular wire format -/// (specifically without name compression). However, in some record data +/// (specifically without name compression). However, in some record data /// types, labels are converted to lowercase for serialization. /// /// - In record owner names, they are compared from the root label outwards, /// with the contents of each label being compared case-insensitively. /// -/// - In record data, they are compared as serialized byte sequences. As +/// - In record data, they are compared as serialized byte sequences. As /// explained above, there are two different valid serializations (i.e. the /// labels may be lowercased, or the original case may be retained). /// @@ -87,13 +87,13 @@ pub use compressor::NameCompressor; /// /// If a domain name type implements [`CanonicalName`], then [`BuildBytes`] /// will serialize the name in the wire format (without changing the case of -/// its labels). [`Ord`] will compare domain names as if they were the owner +/// its labels). [`Ord`] will compare domain names as if they were the owner /// names of records (i.e. not as if they were serialized byte sequences). pub trait CanonicalName: BuildBytes + Ord { /// Serialize a domain name with lowercased labels. /// /// This is subtly different from [`BuildBytes`]; it requires all the - /// characters in the domain name to be lowercased. It is implemented + /// characters in the domain name to be lowercased. It is implemented /// automatically, but it could be overriden for performance. fn build_lowercased_bytes<'b>( &self, @@ -140,7 +140,7 @@ pub trait CanonicalName: BuildBytes + Ord { /// /// This is equivalent to serializing both domain names in the wire format /// using [`build_lowercased_bytes()`] and comparing the resulting byte - /// sequences. It is implemented automatically, but it could be overriden + /// sequences. It is implemented automatically, but it could be overriden /// for performance. /// /// [`build_lowercased_bytes()`]: Self::build_lowercased_bytes() diff --git a/src/new/base/name/reversed.rs b/src/new/base/name/reversed.rs index f40ea8309..e06fddd6b 100644 --- a/src/new/base/name/reversed.rs +++ b/src/new/base/name/reversed.rs @@ -27,9 +27,9 @@ use super::{LabelIter, NameBuf, NameParseError}; /// A domain name in reversed order. /// /// Domain names are conventionally presented and encoded from the innermost -/// label to the root label. This ordering is inconvenient and difficult to +/// label to the root label. This ordering is inconvenient and difficult to /// use, making many common operations (e.g. comparing and ordering domain -/// names) more computationally expensive. A [`RevName`] stores the labels in +/// names) more computationally expensive. A [`RevName`] stores the labels in /// reversed order for more efficient use. #[derive(UnsizedCopy)] #[repr(transparent)] @@ -57,7 +57,7 @@ impl RevName { /// /// # Safety /// - /// The byte sequence must begin with a root label (0-value byte). It + /// The byte sequence must begin with a root label (0-value byte). It /// must be followed by any number of encoded labels, as long as the size /// of the whole string is 255 bytes or less. pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self { @@ -70,7 +70,7 @@ impl RevName { /// /// # Safety /// - /// The byte sequence must begin with a root label (0-value byte). It + /// The byte sequence must begin with a root label (0-value byte). It /// must be followed by any number of encoded labels, as long as the size /// of the whole string is 255 bytes or less. pub unsafe fn from_bytes_unchecked_mut(bytes: &mut [u8]) -> &mut Self { @@ -194,7 +194,7 @@ impl Clone for alloc::boxed::Box { impl PartialEq for RevName { fn eq(&self, that: &Self) -> bool { - // Instead of iterating labels, blindly iterate bytes. The locations + // Instead of iterating labels, blindly iterate bytes. The locations // of labels don't matter since we're testing everything for equality. // NOTE: Label lengths (which are less than 64) aren't affected by @@ -218,9 +218,9 @@ impl PartialOrd for RevName { impl Ord for RevName { fn cmp(&self, that: &Self) -> Ordering { - // Unfortunately, names cannot be compared bytewise. Labels are + // Unfortunately, names cannot be compared bytewise. Labels are // preceded by their length octets, but a longer label can be less - // than a shorter one if its first bytes are less. We are forced to + // than a shorter one if its first bytes are less. We are forced to // compare lexicographically over labels. self.labels().cmp(that.labels()) } @@ -319,11 +319,11 @@ impl<'a> SplitMessageBytes<'a> for RevNameBuf { contents: &'a [u8], start: usize, ) -> Result<(Self, usize), ParseError> { - // NOTE: The input may be controlled by an attacker. Compression + // NOTE: The input may be controlled by an attacker. Compression // pointers can be arranged to cause loops or to access every byte in - // the message in random order. Instead of performing complex loop + // the message in random order. Instead of performing complex loop // detection, which would probably perform allocations, we simply - // disallow a name to point to data _after_ it. Standard name + // disallow a name to point to data _after_ it. Standard name // compressors will never generate such pointers. let mut buffer = Self::empty(); @@ -362,7 +362,7 @@ impl<'a> ParseMessageBytes<'a> for RevNameBuf { contents: &'a [u8], start: usize, ) -> Result { - // See 'split_from_message()' for details. The only differences are + // See 'split_from_message()' for details. The only differences are // in the range of the first iteration, and the check that the first // iteration exactly covers the input range. diff --git a/src/new/base/name/unparsed.rs b/src/new/base/name/unparsed.rs index 563eb22ea..d8ce92806 100644 --- a/src/new/base/name/unparsed.rs +++ b/src/new/base/name/unparsed.rs @@ -14,7 +14,7 @@ use super::Label; /// An unparsed domain name in a DNS message. /// /// Within a DNS message, domain names are stored in conventional order (from -/// innermost to the root label), and may end with a compression pointer. An +/// innermost to the root label), and may end with a compression pointer. An /// [`UnparsedName`] represents this incomplete domain name, exactly as stored /// in a message. #[derive(AsBytes)] @@ -28,7 +28,7 @@ impl UnparsedName { /// /// A domain name can be 255 bytes at most, but an unparsed domain name /// could replace the last byte (representing the root label) with a - /// compression pointer to it. Since compression pointers are 2 bytes, + /// compression pointer to it. Since compression pointers are 2 bytes, /// the total size becomes 256 bytes. pub const MAX_SIZE: usize = 256; @@ -86,7 +86,7 @@ impl UnparsedName { /// The value of this compression pointer. /// /// This returns [`Some`] if the name contains no labels, and only has a - /// compression pointer. The returned value is in the range 0..16384, as + /// compression pointer. The returned value is in the range 0..16384, as /// an offset from the start of the containing DNS message. pub const fn pointer_value(&self) -> Option { if let &[hi @ 0xC0..=0xFF, lo] = self.as_bytes() { diff --git a/src/new/base/parse/mod.rs b/src/new/base/parse/mod.rs index 2cbb9f7ff..82ae2793d 100644 --- a/src/new/base/parse/mod.rs +++ b/src/new/base/parse/mod.rs @@ -1,12 +1,12 @@ //! Parsing DNS messages from the wire format. //! //! At the moment, a high-level or mid-level API for parsing DNS messages is -//! not implemented. This section documents the low-level API. +//! not implemented. This section documents the low-level API. //! //! # Mid-Level API //! //! To parse the questions and records in a [`Message`], use -//! [`Message::parse()`]. To parse a message (including questions and +//! [`Message::parse()`]. To parse a message (including questions and //! records) from bytes, use [`MessageParser::new()`]. //! //! [`Message`]: super::Message @@ -73,7 +73,7 @@ //! //! # Low-Level API //! -//! The low-level API is much more involved. Here's the same example as +//! The low-level API is much more involved. Here's the same example as //! above, but using the low-level API: //! //! ``` @@ -162,7 +162,7 @@ //! //! Individual message items were extracted with [`SplitMessageBytes`] here. //! The low-level API is actually made up of a large number of related parsing -//! traits, and they all have different advantages and limitations. Most of +//! traits, and they all have different advantages and limitations. Most of //! them come from [`super::wire`], which provides bytewise (de)serialization //! but is not aware of DNS-specific considerations. //! @@ -175,14 +175,14 @@ //! If the target type supports [`ParseBytesZC`], that can be used instead. //! [`parse_bytes_by_ref()`] will parse from a reference to a byte sequence. //! This is more efficient than [`ParseBytes`], because it won't copy the -//! data out of the byte sequence. The byte sequence will be re-interpreted +//! data out of the byte sequence. The byte sequence will be re-interpreted //! as an instance of the target type in place, like a pointer cast in C. //! //! [`parse_bytes_by_ref()`]: ParseBytesZC::parse_bytes_by_ref() //! //! If the byte sequence is stored in certain container types, like [`Box`], //! it can also be parsed _in place_ (e.g. `Box<[u8]> -> Box`), via -//! [`parse_bytes_in()`]. The container implements [`ParseBytesInPlace`]; +//! [`parse_bytes_in()`]. The container implements [`ParseBytesInPlace`]; //! see its documentation for a list of implementing types. //! //! [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html @@ -197,26 +197,26 @@ //! //! - If you have a byte sequence and you know that it _starts_ with a certain //! object (and you don't know how many bytes the object takes up), try to -//! use [`SplitBytes::split_bytes()`]. It will return the parsed object and +//! use [`SplitBytes::split_bytes()`]. It will return the parsed object and //! the remainder of the input bytes. //! //! [`SplitBytesZC`] also exists, and works analogously to [`ParseBytesZC`]. //! It is equivalent to but more efficient than [`SplitBytes`], it can work //! for dynamically sized types where [`SplitBytes`] can't, and `&T` will -//! implement [`SplitBytes`] if `T` implements [`SplitBytesZC`]. However, +//! implement [`SplitBytes`] if `T` implements [`SplitBytesZC`]. However, //! there is no `split_bytes_in()`. //! //! - The previous traits don't support decompressing domain names in the DNS //! wire format, since that would also require knowledge of the DNS message -//! containing the bytes being parsed. If you have a byte sequence within a +//! containing the bytes being parsed. If you have a byte sequence within a //! DNS message, and it may contain compressed domain names that need to be -//! resolved, use [`ParseMessageBytes`] or [`SplitMessageBytes`]. These are +//! resolved, use [`ParseMessageBytes`] or [`SplitMessageBytes`]. These are //! analogous to [`ParseBytes`] and [`SplitBytes`], but have different //! parameters. //! //! Note that `ParseMessageBytesZC` or `SplitMessageBytesZC` don't exist, as //! resolving domain names inherently requires copying data from different -//! parts of the DNS message. However, many types that don't contain domain +//! parts of the DNS message. However, many types that don't contain domain //! names still implement [`ParseMessageBytes`] and [`SplitMessageBytes`]. //! If `T` implements [`ParseBytesZC`] or [`SplitBytesZC`], `&T` will also //! implement [`ParseMessageBytes`] and [`SplitMessageBytes`] respectively. @@ -238,8 +238,8 @@ pub trait ParseMessageBytes<'a>: ParseBytes<'a> { /// Parse a value from bytes in a DNS message. /// /// The contents of the DNS message (up to and including the actual bytes - /// to be parsed) is provided as `contents`. The 12-byte message header - /// is not included. `contents[start..]` is the input to be parsed. The + /// to be parsed) is provided as `contents`. The 12-byte message header + /// is not included. `contents[start..]` is the input to be parsed. The /// earlier bytes are provided for resolving compressed domain names. fn parse_message_bytes( contents: &'a [u8], @@ -323,12 +323,12 @@ pub trait SplitMessageBytes<'a>: /// Parse a value from the start of a byte sequence within a DNS message. /// /// The contents of the DNS message (i.e. without the 12-byte header) is - /// provided as `contents`. `contents[start..]` is the beginning of the - /// input to be parsed. The earlier bytes are provided for resolving + /// provided as `contents`. `contents[start..]` is the beginning of the + /// input to be parsed. The earlier bytes are provided for resolving /// compressed domain names. /// /// If parsing is successful, the parsed value and the offset for the rest - /// of the input are returned. If `len` bytes were parsed to form `self`, + /// of the input are returned. If `len` bytes were parsed to form `self`, /// `start + len` should be the returned offset. fn split_message_bytes( contents: &'a [u8], diff --git a/src/new/base/serial.rs b/src/new/base/serial.rs index 65bbe2e43..6804b1036 100644 --- a/src/new/base/serial.rs +++ b/src/new/base/serial.rs @@ -49,7 +49,7 @@ impl Serial { impl Serial { /// Increment this by a non-negative number. /// - /// The number must be in the range `[0, 2^31 - 1]`. An [`i32`] is used + /// The number must be in the range `[0, 2^31 - 1]`. An [`i32`] is used /// instead of a [`u32`] because it is easier to understand and implement /// a non-negative check versus the upper range check. /// diff --git a/src/new/base/wire/build.rs b/src/new/base/wire/build.rs index a322cfe81..9ae16d69f 100644 --- a/src/new/base/wire/build.rs +++ b/src/new/base/wire/build.rs @@ -9,7 +9,7 @@ pub trait BuildBytes { /// Serialize into a byte sequence. /// /// `self` is serialized into a byte sequence and written to the given - /// buffer. If the buffer is large enough, the whole object is written + /// buffer. If the buffer is large enough, the whole object is written /// and the remaining (unmodified) part of the buffer is returned. /// /// If the buffer is too small, a [`TruncationError`] is returned (and @@ -22,7 +22,7 @@ pub trait BuildBytes { /// The size of `self` when serialized into a byte sequence. /// /// This reports the exact number of bytes that will be written to the - /// buffer passed to [`Self::build_bytes()`]. Note that this is not the + /// buffer passed to [`Self::build_bytes()`]. Note that this is not the /// cheapest operation; it may have to traverse all the fields in `self`. fn built_bytes_size(&self) -> usize; } @@ -141,9 +141,9 @@ impl BuildBytes for [T; N] { /// Deriving [`BuildBytes`] automatically. /// -/// [`BuildBytes`] can be derived on `struct`s (not `enum`s or `union`s). The +/// [`BuildBytes`] can be derived on `struct`s (not `enum`s or `union`s). The /// generated implementation will call [`build_bytes()`] with each field, in -/// the order they are declared. The trait implementation will be bounded by +/// the order they are declared. The trait implementation will be bounded by /// the type of every field implementing [`BuildBytes`]. /// /// [`build_bytes()`]: BuildBytes::build_bytes() @@ -221,7 +221,7 @@ unsafe impl AsBytes for [T; N] {} /// Deriving [`AsBytes`] automatically. /// /// [`AsBytes`] can be derived on `struct`s (not `enum`s or `union`s), where a -/// fixed memory layout (`repr(C)` or `repr(transparent)`) is used. Every +/// fixed memory layout (`repr(C)` or `repr(transparent)`) is used. Every /// field must implement [`AsBytes`]. /// /// Here's a simple example: diff --git a/src/new/base/wire/mod.rs b/src/new/base/wire/mod.rs index 5b67871e1..1395cffab 100644 --- a/src/new/base/wire/mod.rs +++ b/src/new/base/wire/mod.rs @@ -1,7 +1,7 @@ //! Low-level byte serialization. //! //! This is a low-level module providing simple and efficient mechanisms to -//! parse data from and build data into byte sequences. It takes inspiration +//! parse data from and build data into byte sequences. It takes inspiration //! from the [zerocopy] crate, but 1) is significantly simpler, 2) has simple //! requirements for its `derive` macros, and 3) supports parsing out-of-place //! (i.e. non-zero-copy). @@ -11,7 +11,7 @@ //! # Design //! //! When a type is defined to represent a component of a network packet, its -//! internal structure should match the structure of its wire format. Here's +//! internal structure should match the structure of its wire format. Here's //! an example of a question in a DNS message: //! //! ``` @@ -30,7 +30,7 @@ //! ``` //! //! This exactly matches the structure of a question on the wire -- the QNAME, -//! the QTYPE, and the QCLASS. This allows the definition of the type to also +//! the QTYPE, and the QCLASS. This allows the definition of the type to also //! specify the wire format concisely. //! //! Now, this type can be read from and written to bytes very easily: @@ -64,7 +64,7 @@ //! - [`BuildBytes`]: For serializing an object and writing it to the _start_ //! of a byte string. //! -//! These operate by value, and copy (some) data from the input. However, +//! These operate by value, and copy (some) data from the input. However, //! there are also zero-copy versions of these traits, which are more //! efficient (but not always applicable): //! @@ -82,11 +82,11 @@ //! Notably, [`u8`], slices, and arrays can be parsed into and built from. //! These form the basic building blocks for every other wire-format type. //! -//! After [`u8`], primitive integer types get somewhat more complicated. To +//! After [`u8`], primitive integer types get somewhat more complicated. To //! facilitate zero-copy parsing, it should be possible to transmute an input -//! byte sequence into a wire-format type in place. This is not possible with +//! byte sequence into a wire-format type in place. This is not possible with //! Rust's built-in integer types, since they have alignment requirements and -//! use the platform's native endianness. Instead, the custom types [`U16`], +//! use the platform's native endianness. Instead, the custom types [`U16`], //! [`U32`], and [`U64`] are provided; these can be used in the wire format. mod build; diff --git a/src/new/base/wire/parse.rs b/src/new/base/wire/parse.rs index 2d844a360..55a96783b 100644 --- a/src/new/base/wire/parse.rs +++ b/src/new/base/wire/parse.rs @@ -11,10 +11,10 @@ use crate::utils::dst::UnsizedCopy; pub trait ParseBytes<'a>: Sized { /// Parse a value of [`Self`] from the given byte sequence. /// - /// The returned value may borrow from the byte sequence. This allows it + /// The returned value may borrow from the byte sequence. This allows it /// to avoid copying data unnecessarily. /// - /// The entirety of the input must be used. If some input bytes would be + /// The entirety of the input must be used. If some input bytes would be /// left over, [`ParseError`] should be returned. fn parse_bytes(bytes: &'a [u8]) -> Result; } @@ -67,7 +67,7 @@ impl<'a> ParseBytes<'a> for alloc::string::String { /// Deriving [`ParseBytes`] automatically. /// -/// [`ParseBytes`] can be derived on `struct`s (not `enum`s or `union`s). All +/// [`ParseBytes`] can be derived on `struct`s (not `enum`s or `union`s). All /// fields except the last must implement [`SplitBytes`], while the last field /// only needs to implement [`ParseBytes`]. /// @@ -106,12 +106,12 @@ pub trait SplitBytes<'a>: Sized + ParseBytes<'a> { /// Parse a value of [`Self`] from the start of the byte sequence. /// /// If parsing is successful, the parsed value and the rest of the input - /// (the part that was not parsed) are returned. On failure, a + /// (the part that was not parsed) are returned. On failure, a /// [`ParseError`] is returned. /// /// ## Non-Greedy Parsing /// - /// This function is _non-greedy_. This can be interpreted in several + /// This function is _non-greedy_. This can be interpreted in several /// equivalent ways: /// /// - If `split_bytes()` returns successfully for some input sequence, it @@ -196,7 +196,7 @@ impl<'a, T: SplitBytes<'a>> SplitBytes<'a> for alloc::boxed::Box { /// Deriving [`SplitBytes`] automatically. /// -/// [`SplitBytes`] can be derived on `struct`s (not `enum`s or `union`s). All +/// [`SplitBytes`] can be derived on `struct`s (not `enum`s or `union`s). All /// fields must implement [`SplitBytes`]. /// /// Here's a simple example: @@ -235,13 +235,13 @@ pub use domain_macros::SplitBytes; /// # Safety /// /// Every implementation of [`ParseBytesZC`] must satisfy the invariants -/// documented on [`parse_bytes_by_ref()`]. An incorrect implementation is +/// documented on [`parse_bytes_by_ref()`]. An incorrect implementation is /// considered to cause undefined behaviour. /// /// [`parse_bytes_by_ref()`]: Self::parse_bytes_by_ref() /// /// Implementing types must also have no alignment (i.e. a valid instance of -/// [`Self`] can occur at any address). This eliminates the possibility of +/// [`Self`] can occur at any address). This eliminates the possibility of /// padding bytes when [`Self`] is part of a larger aggregate type. pub unsafe trait ParseBytesZC: UnsizedCopy + 'static { /// Interpret a byte sequence as an instance of [`Self`]. @@ -250,7 +250,7 @@ pub unsafe trait ParseBytesZC: UnsizedCopy + 'static { /// a different container type, use [`Self::parse_bytes_in()`]. /// /// This will return successfully if and only if the entirety of the given - /// byte sequence can be interpreted as an instance of [`Self`]. It will + /// byte sequence can be interpreted as an instance of [`Self`]. It will /// transmute the bytes reference into a reference to [`Self`] and return /// it. /// @@ -266,7 +266,7 @@ pub unsafe trait ParseBytesZC: UnsizedCopy + 'static { /// Parse bytes within the given container. /// /// Given a container of a byte sequence, this function tries to parse the - /// bytes as a valid instance of `Self`. If this succeeds, the container + /// bytes as a valid instance of `Self`. If this succeeds, the container /// as a whole is converted (in place) to hold `Self`. /// /// This is a convenience method for calling @@ -352,13 +352,13 @@ pub use domain_macros::ParseBytesZC; /// Zero-copy parsing from the start of a byte sequence. /// /// This is an extension of [`ParseBytesZC`] for types which can determine -/// their own length when parsing. It is usually implemented by [`Sized`] +/// their own length when parsing. It is usually implemented by [`Sized`] /// types (where the length is just the size of the type), although it can be /// sometimes implemented by unsized types. /// /// # Non-Greedy Parsing /// -/// This parsing functions provided by this trait are _non-greedy_. This can +/// This parsing functions provided by this trait are _non-greedy_. This can /// be interpreted in several equivalent ways: /// /// - If `split_bytes_by_ref()` returns successfully for some input sequence, it @@ -375,7 +375,7 @@ pub use domain_macros::ParseBytesZC; /// # Safety /// /// Every implementation of [`SplitBytesZC`] must satisfy the invariants -/// documented on [`split_bytes_by_ref()`]. An incorrect implementation is +/// documented on [`split_bytes_by_ref()`]. An incorrect implementation is /// considered to cause undefined behaviour. /// /// [`split_bytes_by_ref()`]: Self::split_bytes_by_ref() @@ -386,9 +386,9 @@ pub unsafe trait SplitBytesZC: ParseBytesZC { /// Interpret the start of a byte sequence as an instance of [`Self`]. /// /// The byte sequence will be validated and re-interpreted as a reference - /// to [`Self`]. The length of [`Self`] will be determined, possibly + /// to [`Self`]. The length of [`Self`] will be determined, possibly /// based on the contents (but not the length!) of the input, and the - /// remaining bytes will be returned. If the input does not begin with a + /// remaining bytes will be returned. If the input does not begin with a /// valid instance of [`Self`], a [`ParseError`] is returned. /// /// ## Invariants @@ -472,7 +472,7 @@ pub use domain_macros::SplitBytesZC; /// Parsing from a byte sequence within an container. /// /// This trait allows various "container types", like [`Box`] and [`Vec`], to -/// parse a stored byte sequence into a different type in place. The target +/// parse a stored byte sequence into a different type in place. The target /// type has to implement [`ParseBytesZC`]. /// /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html @@ -509,7 +509,7 @@ impl<'a> ParseBytesInPlace for &'a mut [u8] { }; // SAFETY: By the invariants of 'parse_bytes_by_ref()', '*parsed' has the - // same address and layout as '*self'. Thus, it is safe to use it to + // same address and layout as '*self'. Thus, it is safe to use it to // reconstitute the reference. Ok(unsafe { &mut *parsed.cast_mut() }) } @@ -528,7 +528,7 @@ impl ParseBytesInPlace for alloc::boxed::Box<[u8]> { }; // SAFETY: By the invariants of 'parse_bytes_by_ref()', '*parsed' has - // the same address and layout as '*self'. Thus, it is safe to use it + // the same address and layout as '*self'. Thus, it is safe to use it // to reconstitute the 'Box'. let _ = alloc::boxed::Box::into_raw(self); Ok(unsafe { alloc::boxed::Box::from_raw(parsed.cast_mut()) }) @@ -548,7 +548,7 @@ impl ParseBytesInPlace for alloc::rc::Rc<[u8]> { }; // SAFETY: By the invariants of 'parse_bytes_by_ref()', '*parsed' has the - // same address and layout as '*self'. Thus, it is safe to use it to + // same address and layout as '*self'. Thus, it is safe to use it to // reconstitute the 'Rc'. let _ = alloc::rc::Rc::into_raw(self); Ok(unsafe { alloc::rc::Rc::from_raw(parsed) }) @@ -568,7 +568,7 @@ impl ParseBytesInPlace for alloc::sync::Arc<[u8]> { }; // SAFETY: By the invariants of 'parse_bytes_by_ref()', '*parsed' has the - // same address and layout as '*self'. Thus, it is safe to use it to + // same address and layout as '*self'. Thus, it is safe to use it to // reconstitute the 'Arc'. let _ = alloc::sync::Arc::into_raw(self); Ok(unsafe { alloc::sync::Arc::from_raw(parsed) }) diff --git a/src/new/base/wire/size_prefixed.rs b/src/new/base/wire/size_prefixed.rs index 65a0b5618..d24674058 100644 --- a/src/new/base/wire/size_prefixed.rs +++ b/src/new/base/wire/size_prefixed.rs @@ -24,35 +24,35 @@ use super::{ /// A wrapper adding a size prefix during serialization. /// -/// DNS messages often contain size-prefixed data. Record data is prefixed by +/// DNS messages often contain size-prefixed data. Record data is prefixed by /// a [`U16`](super::U16), indicating its size in bytes, and NSEC3 salts are -/// prefixed by a [`u8`] with the same meaning. [`SizePrefixed`] wraps such +/// prefixed by a [`u8`] with the same meaning. [`SizePrefixed`] wraps such /// data and handles the logic for (de)serialization. /// /// *Warning:* in order to implement zero-copy (de)serialization, this type /// has a `size` field which always holds the size of `T` (or the size of the -/// currently stored object, if `T` is `?Sized`). If this size overflows `S`, -/// a panic will occur. This can occur even if `T` is only used serialized +/// currently stored object, if `T` is `?Sized`). If this size overflows `S`, +/// a panic will occur. This can occur even if `T` is only used serialized /// via [`ParseBytes`] / [`BuildBytes`], which don't use the `size` field. /// Thus, a 300-byte `T` cannot be used with a `u8` size prefix, even if the -/// `T` serializes into 20 bytes. This almost never occurs in practice. +/// `T` serializes into 20 bytes. This almost never occurs in practice. /// /// ## Bounds /// /// `S` must satisfy various bounds for use in (de)serialization. /// -/// - `S` should almost always implement `TryFrom`. This is needed to -/// initialize it manually, e.g. from the size of `T`. It can be omitted +/// - `S` should almost always implement `TryFrom`. This is needed to +/// initialize it manually, e.g. from the size of `T`. It can be omitted /// for the zero-copy traits [`ParseBytesZC`], [`SplitBytesZC`], and /// [`AsBytes`]. /// /// - During parsing, `S` should implement [`SplitMessageBytes`], -/// [`SplitBytes`], or [`SplitBytesZC`]. It should also implement +/// [`SplitBytes`], or [`SplitBytesZC`]. It should also implement /// `Into`; this is used to read the right number of bytes for the /// actual size-prefixed data. /// /// - During building, `S` should implement [`BuildInMessage`], -/// [`BuildBytes`], or [`AsBytes`]. For the first two, it should also +/// [`BuildBytes`], or [`AsBytes`]. For the first two, it should also /// implement [`Default`]; this is used to temporarily initialize it, to be /// overwritten once the actual size-prefixed data is built (and its size is /// determined). @@ -61,7 +61,7 @@ use super::{ pub struct SizePrefixed { /// The size prefix (needed for 'ParseBytesZC' / 'AsBytes'). /// - /// This field is only used by the zero-copy (de)serialization traits. As + /// This field is only used by the zero-copy (de)serialization traits. As /// such, this field should always be consistent with the size of `data`. size: S, @@ -79,7 +79,7 @@ where /// /// # Panics /// - /// Panics if the size of `data` in memory cannot fit in `S`. This is + /// Panics if the size of `data` in memory cannot fit in `S`. This is /// necessary for `SizePrefixed` to correctly implement [`AsBytes`] and /// [`ParseBytesZC`] / [`SplitBytesZC`]. pub fn new(data: T) -> Self { diff --git a/src/new/edns/cookie.rs b/src/new/edns/cookie.rs index d1469944e..5c3a3acd2 100644 --- a/src/new/edns/cookie.rs +++ b/src/new/edns/cookie.rs @@ -65,7 +65,7 @@ impl ClientCookie { /// Build a [`Cookie`] in response to this request. /// /// A 24-byte version-1 interoperable cookie will be generated and written - /// to the given buffer. If the buffer is big enough, the remaining part + /// to the given buffer. If the buffer is big enough, the remaining part /// of the buffer is returned. #[cfg(feature = "siphasher")] pub fn respond_into<'b>( @@ -169,7 +169,7 @@ impl Cookie { /// The version number of this interoperable cookie. /// /// Assuming this is an interoperable cookie, as specified by [RFC 9018], - /// the 1-byte version number of the cookie is returned. Currently, only + /// the 1-byte version number of the cookie is returned. Currently, only /// version 1 has been specified. /// /// [RFC 9018]: https://datatracker.ietf.org/doc/html/rfc9018 @@ -194,9 +194,9 @@ impl Cookie { /// Verify this cookie. /// /// This cookie is verified as a 24-byte version-1 interoperable cookie, - /// as specified by [RFC 9018]. A 16-byte secret is used to generate a + /// as specified by [RFC 9018]. A 16-byte secret is used to generate a /// hash for this cookie, based on its fields and the IP address of the - /// client which used it. If the cookie was generated in the given time + /// client which used it. If the cookie was generated in the given time /// period, and the generated hash matches the hash in the cookie, it is /// valid. /// diff --git a/src/new/edns/mod.rs b/src/new/edns/mod.rs index 9ebb07a08..73cd49406 100644 --- a/src/new/edns/mod.rs +++ b/src/new/edns/mod.rs @@ -30,8 +30,8 @@ pub use ext_err::{ExtError, ExtErrorCode}; /// An Extended DNS record. /// -/// This is generic over the record data type. It will often be [`&Opt`], but -/// it can also be [`Box`] or an array/slice of [`EdnsOption`]s. While +/// This is generic over the record data type. It will often be [`&Opt`], but +/// it can also be [`Box`] or an array/slice of [`EdnsOption`]s. While /// [`&Opt`] can be used for parsing, all of them can be used for serializing /// into the wire format. /// diff --git a/src/new/mod.rs b/src/new/mod.rs index a3b3b8901..c9390575e 100644 --- a/src/new/mod.rs +++ b/src/new/mod.rs @@ -1,7 +1,7 @@ //! A new API for `domain`. //! //! This module mirrors the top-level layout of `domain`, except that the -//! sub-modules it provides have brand new APIs. These are designed from +//! sub-modules it provides have brand new APIs. These are designed from //! scratch and take advantage of new advances (e.g. in the Rust language //! itself) to provide more ergonomic and efficient interfaces of the same //! functionality. @@ -9,16 +9,16 @@ //! ## About the Domain Name System //! //! In one sentence: DNS is a hierarchial mapping of human-readable _domain -//! names_ to arbitrary information. Its most important function has been +//! names_ to arbitrary information. Its most important function has been //! (and continues to be) to resolve a human-readable name for a server into -//! an IP address: this is the basis for the World Wide Web. Its importance +//! an IP address: this is the basis for the World Wide Web. Its importance //! to the Internet as a whole has led to massive amounts of development //! effort and infrastructure surrounding it. //! //! There are two basic parts to DNS: the information stored in DNS, how it is //! structured, and its management; and the DNS protocol, which is used for -//! communicating that information. The two are naturally linked, but the -//! former is more abstract and the latter is quite practical. Both are +//! communicating that information. The two are naturally linked, but the +//! former is more abstract and the latter is quite practical. Both are //! standardized by a large number of Internet Standards, the most well-known //! of which may be [RFC 1034] and [RFC 1035]. //! @@ -37,7 +37,7 @@ //! DNS is a vast and complex system in practice, due to ambiguity in the //! relevant standards, variation in implementation-defined behaviour, the //! free-form nature of the information stored, and the need for reliability -//! in the face of it all. `domain`'s goal is to help users get DNS right. +//! in the face of it all. `domain`'s goal is to help users get DNS right. //! Its APIs do the right thing by default, while providing the necessary //! fallbacks when users have complex requirements and need manual control. //! @@ -52,13 +52,13 @@ //! ## Doing DNS Manually //! //! When especially irregular operations are required, or custom high-level -//! interfaces need to be built, `domain`'s low-level APIs are useful. The -//! primary entry point for this is the [`base`] module. It defines core DNS +//! interfaces need to be built, `domain`'s low-level APIs are useful. The +//! primary entry point for this is the [`base`] module. It defines core DNS //! data types and implements building to and parsing from the wire format. //! //! Alongside [`base`], [`rdata`] defines the standard DNS record data types, -//! like [`rdata::A`] and [`rdata::Ns`]. It also provides containers which -//! can hold any known or unknown record data type. Together, these modules +//! like [`rdata::A`] and [`rdata::Ns`]. It also provides containers which +//! can hold any known or unknown record data type. Together, these modules //! provide the basic essence of DNS that any operation can be built around. pub mod base; diff --git a/src/new/rdata/basic/a.rs b/src/new/rdata/basic/a.rs index 418639c80..07dd43b3f 100644 --- a/src/new/rdata/basic/a.rs +++ b/src/new/rdata/basic/a.rs @@ -18,7 +18,7 @@ use crate::utils::dst::UnsizedCopy; /// The IPv4 address of a host responsible for this domain. /// /// An [`A`] record indicates that a domain name is backed by a server that -/// can be reached over the Internet at the specified IPv4 address. It does +/// can be reached over the Internet at the specified IPv4 address. It does /// not specify the server's capabilities (e.g. what protocols it supports); /// those have to be communicated elsewhere. /// @@ -29,17 +29,17 @@ use crate::utils::dst::UnsizedCopy; /// ## Wire Format /// /// The wire format of an [`A`] record is the 4 bytes of its IPv4 address, in -/// conventional order (from most to least significant). For example, +/// conventional order (from most to least significant). For example, /// `127.0.0.1` would be serialized as `7F 00 00 01`. /// /// The memory layout of the [`A`] type is identical to its serialization in -/// the wire format. This means it can be parsed from the wire format in a +/// the wire format. This means it can be parsed from the wire format in a /// zero-copy fashion, which is more efficient. /// /// ## Usage /// /// Because [`A`] is a record data type, it is usually handled within an enum -/// like [`RecordData`]. This section describes how to use it independently +/// like [`RecordData`]. This section describes how to use it independently /// (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData @@ -81,7 +81,7 @@ use crate::utils::dst::UnsizedCopy; /// /// To serialize an [`A`] in the wire format, use [`BuildBytes`] (which will /// serialize it to a given buffer) or [`AsBytes`] (which will cast the [`A`] -/// into a byte sequence in place). It also supports [`BuildInMessage`]. +/// into a byte sequence in place). It also supports [`BuildInMessage`]. #[derive( Copy, Clone, diff --git a/src/new/rdata/basic/cname.rs b/src/new/rdata/basic/cname.rs index 7b9ff4c61..50ea62646 100644 --- a/src/new/rdata/basic/cname.rs +++ b/src/new/rdata/basic/cname.rs @@ -16,15 +16,15 @@ use crate::new::base::{ /// The canonical name for this domain. /// -/// A [`CName`] record indicates that a domain name is an alias. Any data +/// A [`CName`] record indicates that a domain name is an alias. Any data /// associated with that domain name originates from the "canonical" domain -/// name (with a few DNSSEC-related exceptions). If a domain name is an +/// name (with a few DNSSEC-related exceptions). If a domain name is an /// alias, it has a single canonical name (see [RFC 2181, section 10.1]); it /// cannot have multiple distinct [`CName`] records. /// /// [RFC 2181, section 10.1]: https://datatracker.ietf.org/doc/html/rfc2181#section-10.1 /// -/// [`CName`] is specified by [RFC 1035, section 3.3.1]. The behaviour of DNS +/// [`CName`] is specified by [RFC 1035, section 3.3.1]. The behaviour of DNS /// lookups and name servers is specified by [RFC 1034, section 3.6.2]. /// /// [RFC 1034, section 3.6.2]: https://datatracker.ietf.org/doc/html/rfc1034#section-3.6.2 @@ -38,14 +38,14 @@ use crate::new::base::{ /// ## Usage /// /// Because [`CName`] is a record data type, it is usually handled within -/// an enum like [`RecordData`]. This section describes how to use it +/// an enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// /// In order to build a [`CName`], it's first important to choose a domain -/// name type. For short-term usage (where the [`CName`] is a local -/// variable), it is common to pick [`RevNameBuf`]. If the [`CName`] will +/// name type. For short-term usage (where the [`CName`] is a local +/// variable), it is common to pick [`RevNameBuf`]. If the [`CName`] will /// be placed on the heap, Box<[`RevName`]> will be more /// efficient. /// @@ -54,7 +54,7 @@ use crate::new::base::{ /// /// The primary way to build a new [`CName`] is to construct each /// field manually. To parse a [`CName`] from a DNS message, use -/// [`ParseMessageBytes`]. In case the input bytes don't use name +/// [`ParseMessageBytes`]. In case the input bytes don't use name /// compression, [`ParseBytes`] can be used. /// /// ``` @@ -81,8 +81,8 @@ use crate::new::base::{ /// ``` /// /// Since [`CName`] is a sized type, and it implements [`Copy`] and [`Clone`], -/// it's straightforward to handle and move around. However, this depends on -/// the domain name type. It can be changed using [`CName::map_name()`] and +/// it's straightforward to handle and move around. However, this depends on +/// the domain name type. It can be changed using [`CName::map_name()`] and /// [`CName::map_name_by_ref()`]. /// /// For debugging, [`CName`] can be formatted using [`fmt::Debug`]. @@ -90,7 +90,7 @@ use crate::new::base::{ /// [`fmt::Debug`]: core::fmt::Debug /// /// To serialize a [`CName`] in the wire format, use [`BuildInMessage`] -/// (which supports name compression). If name compression is not desired, +/// (which supports name compression). If name compression is not desired, /// use [`BuildBytes`]. #[derive( Copy, diff --git a/src/new/rdata/basic/hinfo.rs b/src/new/rdata/basic/hinfo.rs index 7c78df15f..631e96ee6 100644 --- a/src/new/rdata/basic/hinfo.rs +++ b/src/new/rdata/basic/hinfo.rs @@ -19,7 +19,7 @@ use crate::new::base::{ /// Information about the host computer. /// /// [`HInfo`] describes the hardware and software of the server associated -/// with the domain name. It is not commonly used for its original purpose, +/// with the domain name. It is not commonly used for its original purpose, /// given several issues: /// /// 1. A domain name can be associated with multiple servers (due to having @@ -29,15 +29,15 @@ use crate::new::base::{ /// /// 2. The CPU and OS name are expected to be standardized, but given the /// massive (and growing) number of both, it would be impossible to cover -/// every possibility. [RFC 1010] listed the initial set of names, and it +/// every possibility. [RFC 1010] listed the initial set of names, and it /// has evolved into the online lists of [operating system names] (last /// updated in 2010) and [machine names] (last updated in 2001). /// /// 3. As documented by [RFC 1035], the "main use" for [`HInfo`] records was /// "for protocols such as FTP that can use special procedures when talking -/// between machines or operating systems of the same type". But given the +/// between machines or operating systems of the same type". But given the /// portabilitiy of most protocols across machines and operating systems, -/// [`HInfo`] is not very informative. Protocols typically provide +/// [`HInfo`] is not very informative. Protocols typically provide /// extension mechanisms in-band instead of relying on out-of-band DNS /// information. /// @@ -52,7 +52,7 @@ use crate::new::base::{ /// [machine names]: https://www.iana.org/assignments/machine-names/machine-names.xhtml /// /// Recently, [`HInfo`] has gained new use, as a potential fallback response -/// for [`QType::ANY`] queries. [RFC 8482] specifies that name servers +/// for [`QType::ANY`] queries. [RFC 8482] specifies that name servers /// wishing to avoid answering [`QType::ANY`] queries (which are expensive /// to look up, have an amplifying network effect, and can be abused for DoS /// attacks) can respond with a synthesized [`HInfo`] record instead. @@ -60,7 +60,7 @@ use crate::new::base::{ /// [`QType::ANY`]: crate::new::base::QType::ANY /// [RFC 8482]: https://datatracker.ietf.org/doc/html/rfc8482 /// -/// [`HInfo`] is specified by [RFC 1035, section 3.3.2]. Its use as an +/// [`HInfo`] is specified by [RFC 1035, section 3.3.2]. Its use as an /// alternative response to [`QType::ANY`] queries is documented by [RFC 8482, /// section 4.2]. /// @@ -70,14 +70,14 @@ use crate::new::base::{ /// ## Wire Format /// /// The wire format of an [`HInfo`] record is the concatenation of two -/// "character strings" (see [`CharStr`]). The first specifies the "machine +/// "character strings" (see [`CharStr`]). The first specifies the "machine /// name" of the host computer, and the second specifies the name of the /// operating system it is running. /// /// ## Usage /// /// Because [`HInfo`] is a record data type, it is usually handled within an -/// enum like [`RecordData`]. This section describes how to use it +/// enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData @@ -106,8 +106,8 @@ use crate::new::base::{ /// ``` /// /// Since [`HInfo`] is a sized type, and it implements [`Copy`] and [`Clone`], -/// it's straightforward to handle and move around. However, it is bound by -/// the lifetime of the borrowed character strings. At the moment, there is +/// it's straightforward to handle and move around. However, it is bound by +/// the lifetime of the borrowed character strings. At the moment, there is /// no perfect way to own an [`HInfo`] without a lifetime restriction (largely /// because it is not commonly used), however: /// @@ -119,7 +119,7 @@ use crate::new::base::{ /// - If [`bumpalo`] is being used, #[cfg_attr(feature = "bumpalo", doc = " [`HInfo::clone_to_bump()`]")] #[cfg_attr(not(feature = "bumpalo"), doc = " `HInfo::clone_to_bump()`")] -/// can clone an [`HInfo`] over to a bump allocator. This may extend its +/// can clone an [`HInfo`] over to a bump allocator. This may extend its /// lifetime sufficiently for some use cases. /// #[cfg_attr( @@ -135,7 +135,7 @@ use crate::new::base::{ /// /// [`fmt::Debug`]: core::fmt::Debug /// -/// To serialize an [`HInfo`] in the wire format, use [`BuildBytes`]. It also +/// To serialize an [`HInfo`] in the wire format, use [`BuildBytes`]. It also /// supports [`BuildInMessage`]. #[derive( Copy, diff --git a/src/new/rdata/basic/mx.rs b/src/new/rdata/basic/mx.rs index a9b5f0ac0..1b6ae10be 100644 --- a/src/new/rdata/basic/mx.rs +++ b/src/new/rdata/basic/mx.rs @@ -16,7 +16,7 @@ use crate::new::base::{ /// /// An [`Mx`] record indicates that a domain name can receive e-mail, and it /// specifies (the domain name of) the mail server that e-mail for that domain -/// should be sent to. A domain name can be associated with multiple mail +/// should be sent to. A domain name can be associated with multiple mail /// servers (using multiple [`Mx`] records); each one is assigned a priority /// for load balancing. /// @@ -30,27 +30,27 @@ use crate::new::base::{ /// ## Wire Format /// /// The wire format of an [`Mx`] record is the 16-bit preference number (as a -/// big-endian integer) followed by the domain name of the mail server. This +/// big-endian integer) followed by the domain name of the mail server. This /// domain name may be compressed in DNS messages. /// /// ## Usage /// /// Because [`Mx`] is a record data type, it is usually handled within an enum -/// like [`RecordData`]. This section describes how to use it independently +/// like [`RecordData`]. This section describes how to use it independently /// (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// /// In order to build an [`Mx`], it's first important to choose a domain name -/// type. For short-term usage (where the [`Mx`] is a local variable), it is -/// common to pick [`RevNameBuf`]. If the [`Mx`] will be placed on the heap, +/// type. For short-term usage (where the [`Mx`] is a local variable), it is +/// common to pick [`RevNameBuf`]. If the [`Mx`] will be placed on the heap, /// Box<[`RevName`]> will be more efficient. /// /// [`RevName`]: crate::new::base::name::RevName /// [`RevNameBuf`]: crate::new::base::name::RevNameBuf /// /// The primary way to build a new [`Mx`] is to construct each field manually. -/// To parse an [`Mx`] from a DNS message, use [`ParseMessageBytes`]. In case +/// To parse an [`Mx`] from a DNS message, use [`ParseMessageBytes`]. In case /// the input bytes don't use name compression, [`ParseBytes`] can be used. /// /// ``` @@ -77,8 +77,8 @@ use crate::new::base::{ /// ``` /// /// Since [`Mx`] is a sized type, and it implements [`Copy`] and [`Clone`], -/// it's straightforward to handle and move around. However, this depends on -/// the domain name type. It can be changed using [`Mx::map_name()`] and +/// it's straightforward to handle and move around. However, this depends on +/// the domain name type. It can be changed using [`Mx::map_name()`] and /// [`Mx::map_name_by_ref()`]. /// /// For debugging, [`Mx`] can be formatted using [`fmt::Debug`]. @@ -86,7 +86,7 @@ use crate::new::base::{ /// [`fmt::Debug`]: core::fmt::Debug /// /// To serialize an [`Mx`] in the wire format, use [`BuildInMessage`] (which -/// supports name compression). If name compression is not desired, use +/// supports name compression). If name compression is not desired, use /// [`BuildBytes`]. #[derive( Copy, diff --git a/src/new/rdata/basic/ns.rs b/src/new/rdata/basic/ns.rs index a4040ba14..a40a88e49 100644 --- a/src/new/rdata/basic/ns.rs +++ b/src/new/rdata/basic/ns.rs @@ -18,12 +18,12 @@ use crate::new::base::{ /// /// An [`Ns`] record indicates that a domain name is the apex of a DNS zone, /// and it specifies (the domain name of) the name server that queries about -/// the domain name (and its descendants) should be sent to. A domain name +/// the domain name (and its descendants) should be sent to. A domain name /// can be associated with multiple name servers (using multiple [`Ns`] /// records). /// /// DNS is designed around the concept of delegating responsibility for domain -/// names. If a name server responds to a query with an empty answer section, +/// names. If a name server responds to a query with an empty answer section, /// but with [`Ns`] records in the authority section, it is claiming to not be /// the authoritative source of information about the queried domain name; /// the [`Ns`] records specify name servers to whom that authority has been @@ -40,26 +40,26 @@ use crate::new::base::{ /// ## Wire format /// /// The wire format of an [`Ns`] record is simply the domain name of the name -/// server. This domain name may be compressed in DNS messages. +/// server. This domain name may be compressed in DNS messages. /// /// ## Usage /// /// Because [`Ns`] is a record data type, it is usually handled within an enum -/// like [`RecordData`]. This section describes how to use it independently +/// like [`RecordData`]. This section describes how to use it independently /// (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// /// In order to build an [`Ns`], it's first important to choose a domain name -/// type. For short-term usage (where the [`Ns`] is a local variable), it is -/// common to pick [`RevNameBuf`]. If the [`Ns`] will be placed on the heap, +/// type. For short-term usage (where the [`Ns`] is a local variable), it is +/// common to pick [`RevNameBuf`]. If the [`Ns`] will be placed on the heap, /// Box<[`RevName`]> will be more efficient. /// /// [`RevName`]: crate::new::base::name::RevName /// [`RevNameBuf`]: crate::new::base::name::RevNameBuf /// /// The primary way to build a new [`Ns`] is to construct each field manually. -/// To parse an [`Ns`] from a DNS message, use [`ParseMessageBytes`]. In case +/// To parse an [`Ns`] from a DNS message, use [`ParseMessageBytes`]. In case /// the input bytes don't use name compression, [`ParseBytes`] can be used. /// /// ``` @@ -86,8 +86,8 @@ use crate::new::base::{ /// ``` /// /// Since [`Ns`] is a sized type, and it implements [`Copy`] and [`Clone`], -/// it's straightforward to handle and move around. However, this depends on -/// the domain name type. It can be changed using [`Ns::map_name()`] and +/// it's straightforward to handle and move around. However, this depends on +/// the domain name type. It can be changed using [`Ns::map_name()`] and /// [`Ns::map_name_by_ref()`]. /// /// For debugging, [`Ns`] can be formatted using [`fmt::Debug`]. @@ -95,7 +95,7 @@ use crate::new::base::{ /// [`fmt::Debug`]: core::fmt::Debug /// /// To serialize an [`Ns`] in the wire format, use [`BuildInMessage`] (which -/// supports name compression). If name compression is not desired, use +/// supports name compression). If name compression is not desired, use /// [`BuildBytes`]. #[derive( Copy, diff --git a/src/new/rdata/basic/ptr.rs b/src/new/rdata/basic/ptr.rs index 7312a406c..54c46e0ee 100644 --- a/src/new/rdata/basic/ptr.rs +++ b/src/new/rdata/basic/ptr.rs @@ -15,9 +15,9 @@ use crate::new::base::{ /// A pointer to another domain name. /// /// A [`Ptr`] record is used with special domain names for pointing to other -/// locations in the domain name space. It is conventionally used for reverse +/// locations in the domain name space. It is conventionally used for reverse /// lookups: for example, the [`Ptr`] record for `.in-addr.arpa` points -/// to the domain name using the IPv4 `` in an [`A`] record. The same +/// to the domain name using the IPv4 `` in an [`A`] record. The same /// technique works with `.ip6.arpa` for IPv6 addresses. /// /// [`A`]: crate::new::rdata::A @@ -29,26 +29,26 @@ use crate::new::base::{ /// ## Wire format /// /// The wire format of a [`Ptr`] record is simply the domain name of the name -/// server. This domain name may be compressed in DNS messages. +/// server. This domain name may be compressed in DNS messages. /// /// ## Usage /// /// Because [`Ptr`] is a record data type, it is usually handled within -/// an enum like [`RecordData`]. This section describes how to use it +/// an enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// /// In order to build a [`Ptr`], it's first important to choose a domain name -/// type. For short-term usage (where the [`Ptr`] is a local variable), it is -/// common to pick [`RevNameBuf`]. If the [`Ptr`] will be placed on the heap, +/// type. For short-term usage (where the [`Ptr`] is a local variable), it is +/// common to pick [`RevNameBuf`]. If the [`Ptr`] will be placed on the heap, /// Box<[`RevName`]> will be more efficient. /// /// [`RevName`]: crate::new::base::name::RevName /// [`RevNameBuf`]: crate::new::base::name::RevNameBuf /// /// The primary way to build a new [`Ptr`] is to construct each field manually. -/// To parse a [`Ptr`] from a DNS message, use [`ParseMessageBytes`]. In case +/// To parse a [`Ptr`] from a DNS message, use [`ParseMessageBytes`]. In case /// the input bytes don't use name compression, [`ParseBytes`] can be used. /// /// ``` @@ -75,8 +75,8 @@ use crate::new::base::{ /// ``` /// /// Since [`Ptr`] is a sized type, and it implements [`Copy`] and [`Clone`], -/// it's straightforward to handle and move around. However, this depends on -/// the domain name type. It can be changed using [`Ptr::map_name()`] and +/// it's straightforward to handle and move around. However, this depends on +/// the domain name type. It can be changed using [`Ptr::map_name()`] and /// [`Ptr::map_name_by_ref()`]. /// /// For debugging, [`Ptr`] can be formatted using [`fmt::Debug`]. @@ -84,7 +84,7 @@ use crate::new::base::{ /// [`fmt::Debug`]: core::fmt::Debug /// /// To serialize a [`Ptr`] in the wire format, use [`BuildInMessage`] (which -/// supports name compression). If name compression is not desired, use +/// supports name compression). If name compression is not desired, use /// [`BuildBytes`]. #[derive( Copy, diff --git a/src/new/rdata/basic/soa.rs b/src/new/rdata/basic/soa.rs index b4b18b48f..813436b65 100644 --- a/src/new/rdata/basic/soa.rs +++ b/src/new/rdata/basic/soa.rs @@ -18,7 +18,7 @@ use crate::new::base::{CanonicalRecordData, Serial}; /// It provides several parameters to describe how the zone should be used, /// e.g. how often it should be refreshed. /// -/// [`Soa`]'s most important use is to detect changes to the zone. Whenever +/// [`Soa`]'s most important use is to detect changes to the zone. Whenever /// the zone is changed, [`Soa::serial`] is incremented; secondary DNS servers /// (which cache and redistribute the contents of the zone) can thus detect /// whether they need to update their cache. @@ -29,7 +29,7 @@ use crate::new::base::{CanonicalRecordData, Serial}; /// The zone (along with its authoritative name servers) is authoritative for /// the record. /// -/// [`Soa`] is specified by [RFC 1035, section 3.3.13]. The behaviour of +/// [`Soa`] is specified by [RFC 1035, section 3.3.13]. The behaviour of /// secondary name servers using [`Soa`] to check for updates to a zone is /// specified by [RFC 1034, section 4.3.5]. /// @@ -39,21 +39,21 @@ use crate::new::base::{CanonicalRecordData, Serial}; /// ## Wire format /// /// The wire format of a [`Soa`] record is the concatenation of its fields, in -/// the same order as the `struct` definition. The domain names within a -/// [`Soa`] may be compressed in DNS messages. Every other field is an +/// the same order as the `struct` definition. The domain names within a +/// [`Soa`] may be compressed in DNS messages. Every other field is an /// unsigned 32-bit big-endian integer. /// /// ## Usage /// /// Because [`Soa`] is a record data type, it is usually handled within -/// an enum like [`RecordData`]. This section describes how to use it +/// an enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// /// In order to build a [`Soa`], it's first important to choose a domain name -/// type. For short-term usage (where the [`Soa`] is a local variable), it is -/// common to pick [`RevNameBuf`]. If the [`Soa`] will be placed on the heap, +/// type. For short-term usage (where the [`Soa`] is a local variable), it is +/// common to pick [`RevNameBuf`]. If the [`Soa`] will be placed on the heap, /// Box<[`RevName`]> will be more efficient. /// /// [`RevName`]: crate::new::base::name::RevName @@ -61,7 +61,7 @@ use crate::new::base::{CanonicalRecordData, Serial}; /// /// The primary way to build a new [`Soa`] is to construct each /// field manually. To parse a [`Soa`] from a DNS message, use -/// [`ParseMessageBytes`]. In case the input bytes don't use name +/// [`ParseMessageBytes`]. In case the input bytes don't use name /// compression, [`ParseBytes`] can be used. /// /// ``` @@ -101,8 +101,8 @@ use crate::new::base::{CanonicalRecordData, Serial}; /// ``` /// /// Since [`Soa`] is a sized type, and it implements [`Copy`] and [`Clone`], -/// it's straightforward to handle and move around. However, this depends on -/// the domain name type. It can be changed using [`Soa::map_names()`] and +/// it's straightforward to handle and move around. However, this depends on +/// the domain name type. It can be changed using [`Soa::map_names()`] and /// [`Soa::map_names_by_ref()`]. /// /// For debugging, [`Soa`] can be formatted using [`fmt::Debug`]. @@ -110,7 +110,7 @@ use crate::new::base::{CanonicalRecordData, Serial}; /// [`fmt::Debug`]: core::fmt::Debug /// /// To serialize a [`Soa`] in the wire format, use [`BuildInMessage`] -/// (which supports name compression). If name compression is not desired, +/// (which supports name compression). If name compression is not desired, /// use [`BuildBytes`]. #[derive( Copy, @@ -129,7 +129,7 @@ pub struct Soa { /// This domain name should point to a name server that is authoritative /// for this zone -- more specifically, that is the original source of /// information that all other name servers are (directly or indirectly) - /// loading this zone from. This need not be listed in the [`Ns`] records + /// loading this zone from. This need not be listed in the [`Ns`] records /// for this zone, if it is not intended for public querying. /// /// [`Ns`]: crate::new::rdata::Ns @@ -138,9 +138,9 @@ pub struct Soa { /// The mailbox of the maintainer of this zone. /// /// The first label here is the username (i.e. local part) of the e-mail - /// address, and the remaining labels make up the mail domain name. For + /// address, and the remaining labels make up the mail domain name. For /// example, would be represented as - /// `hostmaster.sri-nic.arpa`. This convention is specified in [RFC 1034, + /// `hostmaster.sri-nic.arpa`. This convention is specified in [RFC 1034, /// section 3.3]. /// /// [RFC 1034, section 3.3]: https://datatracker.ietf.org/doc/html/rfc1034#section-3.3 @@ -148,21 +148,21 @@ pub struct Soa { /// The version number of the original copy of this zone. /// - /// This value is increased when the contents of the zone change. If a + /// This value is increased when the contents of the zone change. If a /// secondary name server wishes to cache the contents of this zone, it /// can periodically check the version number from the primary name server /// to determine whether it needs to update its cache. /// - /// There are multiple conventions for versioning strategies. Some zones + /// There are multiple conventions for versioning strategies. Some zones /// will increase this value by 1 when a change occurs; some set it to the /// Unix timestamp of the latest change; others set it so that the decimal - /// representation includes the current date. As long as the version + /// representation includes the current date. As long as the version /// number increases (by a relatively small value) upon every change, any /// strategy is valid. /// /// This field is represented using [`Serial`], which provides special - /// "sequence space arithmetic". This ensures that ordering comparisons - /// are well-defined even if the number overflows modulo `2^32`. See its + /// "sequence space arithmetic". This ensures that ordering comparisons + /// are well-defined even if the number overflows modulo `2^32`. See its /// documentation for more information. pub serial: Serial, @@ -170,7 +170,7 @@ pub struct Soa { /// /// If a secondary name server is caching and serving a zone, it is /// expected to periodically check the zone's serial number in the - /// primary name server for changes to the zone contents. The server is + /// primary name server for changes to the zone contents. The server is /// expected to wait this long (in seconds) after the last successful /// check, before checking again. /// @@ -187,7 +187,7 @@ pub struct Soa { /// /// If a secondary name server is caching and serving a zone, it is /// expected to periodically check the zone's serial number in the - /// primary name server for changes to the zone contents. The server is + /// primary name server for changes to the zone contents. The server is /// expected to wait this long (in seconds) after the last _failing_ check /// before trying again. /// @@ -199,7 +199,7 @@ pub struct Soa { /// /// If a secondary name server is caching and serving a zone, it is /// expected to periodically check the zone's serial number in the - /// primary name server for changes to the zone contents. If the server + /// primary name server for changes to the zone contents. If the server /// fails to check for or retrieve updates to the zone for this period of /// time (in seconds), it should consider its copy of the zone obsolete /// and should discard it. @@ -207,9 +207,9 @@ pub struct Soa { /// The minimum TTL for any record in this zone. /// - /// The meaning of this field has changed over time. According to [RFC + /// The meaning of this field has changed over time. According to [RFC /// 2308, section 4], it is the time for which a negative response (i.e. - /// that a certain record does not exist) should be cached. [RFC 4035, + /// that a certain record does not exist) should be cached. [RFC 4035, /// section 2.3] likewise states that the [`NSec`] records for a zone /// should have a TTL of this value. /// diff --git a/src/new/rdata/basic/txt.rs b/src/new/rdata/basic/txt.rs index 6e707a0f4..8ad2da51d 100644 --- a/src/new/rdata/basic/txt.rs +++ b/src/new/rdata/basic/txt.rs @@ -16,13 +16,13 @@ use crate::utils::dst::UnsizedCopy; /// Free-form text strings about this domain. /// /// A [`Txt`] record holds a collection of "strings" (really byte sequences), -/// with no fixed purpose. Usually, a [`Txt`] record holds a single string; +/// with no fixed purpose. Usually, a [`Txt`] record holds a single string; /// if data has to be stored for different purposes, multiple [`Txt`] records /// would be used. /// /// Currently, [`Txt`] records are used systematically for e-mail security, /// e.g. in SPF ([RFC 7208, section 3]), DKIM ([RFC 6376, section 3.6.2]), and -/// DMARC ([RFC 7489, section 6.1]). As a record data type with no strict +/// DMARC ([RFC 7489, section 6.1]). As a record data type with no strict /// semantics and arbitrary data storage, it is likely to continue being /// used. /// @@ -37,30 +37,30 @@ use crate::utils::dst::UnsizedCopy; /// ## Wire Format /// /// The wire format of a [`Txt`] record is the concatenation of a (non-empty) -/// sequence of "character strings" (see [`CharStr`]). A character string is +/// sequence of "character strings" (see [`CharStr`]). A character string is /// serialized as a 1-byte length, followed by up to 255 bytes of content. /// /// The memory layout of the [`Txt`] type is identical to its serialization in -/// the wire format. This means it can be parsed from the wire format in a +/// the wire format. This means it can be parsed from the wire format in a /// zero-copy fashion, which is more efficient. /// /// ## Usage /// /// Because [`Txt`] is a record data type, it is usually handled within -/// an enum like [`RecordData`]. This section describes how to use it +/// an enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// -/// [`Txt`] is a _dynamically sized type_ (DST). It is not possible to store +/// [`Txt`] is a _dynamically sized type_ (DST). It is not possible to store /// a [`Txt`] in place (e.g. in a local variable); it must be held indirectly, -/// via a reference or a smart pointer type like [`Box`]. This makes it more +/// via a reference or a smart pointer type like [`Box`]. This makes it more /// difficult to _create_ new [`Txt`]s; but once they are placed somewhere, /// they can be used by reference (i.e. `&Txt`) exactly like any other type. /// /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html /// -/// It is currently a bit difficult to build a new [`Txt`] from scratch. It +/// It is currently a bit difficult to build a new [`Txt`] from scratch. It /// is easiest to build the wire format representation of the [`Txt`] manually /// (by building a sequence of [`CharStr`]s) and then to parse it. /// @@ -91,8 +91,8 @@ use crate::utils::dst::UnsizedCopy; /// assert_eq!(from_bytes, &*from_boxed_bytes); /// ``` /// -/// As a DST, [`Txt`] does not implement [`Copy`] or [`Clone`]. Instead, it -/// implements [`UnsizedCopy`]. A [`Txt`], held by reference, can be copied +/// As a DST, [`Txt`] does not implement [`Copy`] or [`Clone`]. Instead, it +/// implements [`UnsizedCopy`]. A [`Txt`], held by reference, can be copied /// into a different container (e.g. `Box`) using [`unsized_copy_into()`]. /// /// [`unsized_copy_into()`]: UnsizedCopy::unsized_copy_into() @@ -101,7 +101,7 @@ use crate::utils::dst::UnsizedCopy; /// /// To serialize a [`Txt`] in the wire format, use [`BuildBytes`] (which /// will serialize it to a given buffer) or [`AsBytes`] (which will -/// cast the [`Txt`] into a byte sequence in place). It also supports +/// cast the [`Txt`] into a byte sequence in place). It also supports /// [`BuildInMessage`]. #[derive(AsBytes, BuildBytes, UnsizedCopy)] #[repr(transparent)] @@ -119,7 +119,7 @@ impl Txt { /// /// The byte sequence must a valid instance of [`Txt`] in the wire format; /// it must contain one or more serialized [`CharStr`]s, concatenated - /// together. The byte sequence must be at most 65,535 bytes long. + /// together. The byte sequence must be at most 65,535 bytes long. pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self { // SAFETY: 'Txt' is 'repr(transparent)' to '[u8]'. unsafe { core::mem::transmute::<&[u8], &Txt>(bytes) } diff --git a/src/new/rdata/dname.rs b/src/new/rdata/dname.rs index f09868b35..7def7a249 100644 --- a/src/new/rdata/dname.rs +++ b/src/new/rdata/dname.rs @@ -22,9 +22,9 @@ use crate::utils::dst::UnsizedCopy; /// /// A [`DName`] record indicates that a doamin name is a (partial!) alias. /// Queries for data _under_ that domain name (not that domain name itself) -/// are redirected to the specified target. A domain name can have at most -/// one [`DName`] record; in this case, it cannot define subordinate records -/// nor have a [`CName`] record. It is conceptually similar to [`CName`]. +/// are redirected to the specified target. A domain name can have at most one +/// [`DName`] record; in this case, it cannot define subordinate records nor +/// have a [`CName`] record. It is conceptually similar to [`CName`]. /// /// [`DName`] is specified by [RFC 6672]. /// @@ -37,28 +37,28 @@ use crate::utils::dst::UnsizedCopy; /// This domain name *cannot* be compressed in DNS messages. /// /// The memory layout of the [`DName`] type is identical to its serialization -/// in the wire format. This means that it can be parsed from the wire format +/// in the wire format. This means that it can be parsed from the wire format /// in a zero-copy fashion, which is more efficient. /// /// ## Usage /// /// Because [`DName`] is a record data type, it is usually handled within -/// an enum like [`RecordData`]. This section describes how to use it +/// an enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// -/// [`DName`] is a _dynamically sized type_ (DST). It is not possible to +/// [`DName`] is a _dynamically sized type_ (DST). It is not possible to /// store an [`DName`] in place (e.g. in a local variable); it must be held -/// indirectly, via a reference or a smart pointer type like [`Box`]. This +/// indirectly, via a reference or a smart pointer type like [`Box`]. This /// makes it more difficult to _create_ new [`DName`]s; but once they are /// placed somewhere, they can be used by reference (i.e. `&DName`) exactly /// like any other type. /// /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html /// -/// It is currently a bit difficult to build a new [`DName`] from scratch. It -/// is easiest to use [`DName::new()`] on a reference to a [`Name`], or to +/// It is currently a bit difficult to build a new [`DName`] from scratch. +/// It is easiest to use [`DName::new()`] on a reference to a [`Name`], or to /// build the wire format representation of the [`DName`] manually and then to /// parse it. /// @@ -81,8 +81,8 @@ use crate::utils::dst::UnsizedCopy; /// let heaped: Box = dname.unsized_copy_into(); /// ``` /// -/// As a DST, [`DName`] does not implement [`Copy`] or [`Clone`]. Instead, it -/// implements [`UnsizedCopy`]. A [`DName`], held by reference, can be copied +/// As a DST, [`DName`] does not implement [`Copy`] or [`Clone`]. Instead, it +/// implements [`UnsizedCopy`]. A [`DName`], held by reference, can be copied /// into a different container (e.g. `Box`) using [`unsized_copy_into()`] /// /// [`unsized_copy_into()`]: UnsizedCopy::unsized_copy_into() @@ -93,7 +93,7 @@ use crate::utils::dst::UnsizedCopy; /// /// To serialize a [`DName`] in the wire format, use [`BuildBytes`] /// (which will serialize it to a given buffer) or [`AsBytes`] (which will -/// cast the [`DName`] into a byte sequence in place). It also supports +/// cast the [`DName`] into a byte sequence in place). It also supports /// [`BuildInMessage`]. #[derive( Debug, diff --git a/src/new/rdata/dnssec/nsec.rs b/src/new/rdata/dnssec/nsec.rs index 8bb85cf2b..c578dd5c0 100644 --- a/src/new/rdata/dnssec/nsec.rs +++ b/src/new/rdata/dnssec/nsec.rs @@ -150,7 +150,7 @@ impl TypeBitmaps { }; // At most 32 bytes are necessary, to cover the 256 types that could - // be stored in this window. And empty windows are not allowed. + // be stored in this window. And empty windows are not allowed. if !(1..=32).contains(&len) || rest.len() < len as usize { return Err(ParseError); } diff --git a/src/new/rdata/edns.rs b/src/new/rdata/edns.rs index 108cd7b82..f6b97630c 100644 --- a/src/new/rdata/edns.rs +++ b/src/new/rdata/edns.rs @@ -24,10 +24,10 @@ use crate::utils::dst::UnsizedCopy; /// EDNS options. /// /// An [`Opt`] record holds an unordered set of [`EdnsOption`]s, which provide -/// additional non-critical information about the containing DNS message. It +/// additional non-critical information about the containing DNS message. It /// has fairly different semantics from other record data types, since it only /// exists for communication between peers (it is not part of any zone, and it -/// is not cached). As such, it is often called a "pseudo-RR". +/// is not cached). As such, it is often called a "pseudo-RR". /// /// A record containing [`Opt`] data is interpreted differently from records /// containing normal data types (its class and TTL fields are different). @@ -37,7 +37,7 @@ use crate::utils::dst::UnsizedCopy; /// [`EdnsRecord`]: crate::new::edns::EdnsRecord /// [`Record`]: crate::new::base::Record /// -/// [`Opt`] is specified by [RFC 6891, section 6]. For more information about +/// [`Opt`] is specified by [RFC 6891, section 6]. For more information about /// EDNS, see [`crate::new::edns`]. /// /// [RFC 6891, section 6]: https://datatracker.ietf.org/doc/html/rfc6891#section-6 @@ -45,32 +45,32 @@ use crate::utils::dst::UnsizedCopy; /// ## Wire Format /// /// The wire format of an [`Opt`] record is the concatenation of zero or more -/// EDNS options. An EDNS option is serialized as a 16-bit big-endian code +/// EDNS options. An EDNS option is serialized as a 16-bit big-endian code /// (specifying the meaning of the option), a 16-bit big-endian size (the size /// of the option data), and the variable-length option data. /// /// The memory layout of the [`Opt`] type is identical to its serialization in -/// the wire format. This means that it can be parsed from the wire format in +/// the wire format. This means that it can be parsed from the wire format in /// a zero-copy fashion, which is more efficient. /// /// ## Usage /// /// Because [`Opt`] is a record data type, it is usually handled within an -/// enum like [`RecordData`]. This section describes how to use it +/// enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData /// -/// [`Opt`] is a _dynamically sized type_ (DST). It is not possible to +/// [`Opt`] is a _dynamically sized type_ (DST). It is not possible to /// store an [`Opt`] in place (e.g. in a local variable); it must be held -/// indirectly, via a reference or a smart pointer type like [`Box`]. This +/// indirectly, via a reference or a smart pointer type like [`Box`]. This /// makes it more difficult to _create_ new [`Opt`]s; but once they are placed /// somewhere, they can be used by reference (i.e. `&Opt`) exactly like any /// other type. /// /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html /// -/// It is currently a bit difficult to build a new [`Opt`] from scratch. It +/// It is currently a bit difficult to build a new [`Opt`] from scratch. It /// is easiest to build the wire format representation of the [`Opt`] manually /// (by building a sequence of [`EdnsOption`]s) and then to parse it. /// @@ -109,8 +109,8 @@ use crate::utils::dst::UnsizedCopy; /// assert_eq!(from_bytes, &*from_boxed_bytes); /// ``` /// -/// As a DST, [`Opt`] does not implement [`Copy`] or [`Clone`]. Instead, it -/// implements [`UnsizedCopy`]. An [`Opt`], held by reference, can be copied +/// As a DST, [`Opt`] does not implement [`Copy`] or [`Clone`]. Instead, it +/// implements [`UnsizedCopy`]. An [`Opt`], held by reference, can be copied /// into a different container (e.g. `Box`) using [`unsized_copy_into()`] /// /// [`unsized_copy_into()`]: UnsizedCopy::unsized_copy_into() @@ -119,7 +119,7 @@ use crate::utils::dst::UnsizedCopy; /// /// To serialize a [`Opt`] in the wire format, use [`BuildBytes`] (which /// will serialize it to a given buffer) or [`AsBytes`] (which will -/// cast the [`Opt`] into a byte sequence in place). It also supports +/// cast the [`Opt`] into a byte sequence in place). It also supports /// [`BuildInMessage`]. #[derive(AsBytes, BuildBytes, UnsizedCopy)] #[repr(transparent)] @@ -146,7 +146,7 @@ impl Opt { /// The byte sequence must a valid instance of [`Opt`] in the wire format; /// it must contain a sequence of [`EdnsOption`]s, concatenated together. /// The contents of each [`EdnsOption`] need not be valid (i.e. they can - /// be incorrect with respect to the underlying option type). The byte + /// be incorrect with respect to the underlying option type). The byte /// sequence must be at most 65,535 bytes long. pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self { // SAFETY: 'Opt' is 'repr(transparent)' to '[u8]'. diff --git a/src/new/rdata/ipv6.rs b/src/new/rdata/ipv6.rs index 15fc42155..4958e0a01 100644 --- a/src/new/rdata/ipv6.rs +++ b/src/new/rdata/ipv6.rs @@ -25,11 +25,11 @@ use crate::utils::dst::UnsizedCopy; /// The IPv6 address of a host responsible for this domain. /// /// A [`Aaaa`] record indicates that a domain name is backed by a server that -/// can be reached over the Internet at the specified IPv6 address. It does +/// can be reached over the Internet at the specified IPv6 address. It does /// not specify the server's capabilities (e.g. what protocols it supports); /// those have to be communicated elsewhere. /// -/// [`Aaaa`] is specified by [RFC 3596, section 2]. It works identically to +/// [`Aaaa`] is specified by [RFC 3596, section 2]. It works identically to /// the [`A`] record. /// /// [`A`]: crate::new::rdata::A @@ -38,18 +38,18 @@ use crate::utils::dst::UnsizedCopy; /// ## Wire Format /// /// The wire format of a [`Aaaa`] record is the 16 bytes of its IPv6 address, -/// in conventional order (from most to least significant). For example, +/// in conventional order (from most to least significant). For example, /// `2001::db8::` would be serialized as `20 01 0D B8 00 00 00 00 00 00 00 00 /// 00 00 00 00`. /// /// The memory layout of the [`Aaaa`] type is identical to its serialization -/// in the wire format. This means it can be parsed from the wire format in a +/// in the wire format. This means it can be parsed from the wire format in a /// zero-copy fashion, which is more efficient. /// /// ## Usage /// /// Because [`Aaaa`] is a record data type, it is usually handled within -/// an enum like [`RecordData`]. This section describes how to use it +/// an enum like [`RecordData`]. This section describes how to use it /// independently (or when building new record data from scratch). /// /// [`RecordData`]: crate::new::rdata::RecordData @@ -94,7 +94,7 @@ use crate::utils::dst::UnsizedCopy; /// /// To serialize a [`Aaaa`] in the wire format, use [`BuildBytes`] (which /// will serialize it to a given buffer) or [`AsBytes`] (which will -/// cast the [`Aaaa`] into a byte sequence in place). It also supports +/// cast the [`Aaaa`] into a byte sequence in place). It also supports /// [`BuildInMessage`]. #[derive( Copy, diff --git a/src/new/rdata/mod.rs b/src/new/rdata/mod.rs index 46b852f9e..84d32895f 100644 --- a/src/new/rdata/mod.rs +++ b/src/new/rdata/mod.rs @@ -3,34 +3,34 @@ //! ## Containers for record data //! //! When you need data for a particular record type, you can use the matching -//! concrete type for it. Otherwise, the record data can be held in one of +//! concrete type for it. Otherwise, the record data can be held in one of //! the following types: //! //! - [`RecordData`] is useful for short-term usage, e.g. when manipulating a -//! DNS message or parsing into a custom representation. It can be parsed +//! DNS message or parsing into a custom representation. It can be parsed //! from the wire format very efficiently. //! #![cfg_attr(feature = "alloc", doc = " - [`BoxedRecordData`] ")] #![cfg_attr(not(feature = "alloc"), doc = " - `BoxedRecordData` ")] -//! is useful for long-term storage. For long-term storage of a whole DNS +//! is useful for long-term storage. For long-term storage of a whole DNS //! zone, it's more advisable to use the "zone tree" types provided by this //! crate. //! //! - [`UnparsedRecordData`] is a niche type, useful for low-level -//! manipulation of the DNS wire format. Beware that it can contain +//! manipulation of the DNS wire format. Beware that it can contain //! unresolved name compression pointers. //! //! - [`UnknownRecordData`] can be used to represent data types that aren't -//! supported yet. It functions similarly to [`UnparsedRecordData`], but +//! supported yet. It functions similarly to [`UnparsedRecordData`], but //! it can't be used for many "basic" record data types, like [`Soa`] and -//! [`Mx`]. These types come with many special cases that +//! [`Mx`]. These types come with many special cases that //! [`UnknownRecordData`] doesn't try to account for. //! //! [`UnparsedRecordData`]: crate::new::base::UnparsedRecordData //! //! ## Supported data types //! -//! The following record data types are supported. They are enumerated by +//! The following record data types are supported. They are enumerated by //! [`RecordData`], which can store any one of them at a time. //! //! Basic record types (RFC 1035): @@ -469,22 +469,22 @@ impl<'a, N: SplitMessageBytes<'a>> ParseRecordData<'a> for RecordData<'a, N> { /// A heap-allocated container for [`RecordData`]. /// -/// This is an efficient heap-allocated container for DNS record data. While +/// This is an efficient heap-allocated container for DNS record data. While /// it does not directly provide much functionality, it has getters to access /// the [`RecordData`] within. /// /// ## Performance /// -/// On 64-bit machines, [`BoxedRecordData`] has a size of 16 bytes. This is +/// On 64-bit machines, [`BoxedRecordData`] has a size of 16 bytes. This is /// significantly better than [`RecordData`], which is usually 64 bytes in -/// size. Since [`BoxedRecordData`] is intended for long-term storage and +/// size. Since [`BoxedRecordData`] is intended for long-term storage and /// use, it trades off ergonomics for lower memory usage. #[cfg(feature = "alloc")] pub struct BoxedRecordData { /// A pointer to the record data. /// /// This is the raw pointer backing a `Box<[u8]>` (its size is stored in - /// the `size` field). It is owned by this type. + /// the `size` field). It is owned by this type. data: *mut u8, /// The record data type. @@ -511,11 +511,11 @@ impl BoxedRecordData { // SAFETY: // // As documented on 'BoxedRecordData', 'data' and 'size' form the - // pointer and length of a 'Box<[u8]>'. This pointer is identical to + // pointer and length of a 'Box<[u8]>'. This pointer is identical to // the pointer returned by 'Box::deref()', so we use it directly. // // The lifetime of the returned slice is within the lifetime of 'self' - // which is a shared borrow of the 'BoxedRecordData'. As such, the + // which is a shared borrow of the 'BoxedRecordData'. As such, the // underlying 'Box<[u8]>' outlives the returned slice. unsafe { core::slice::from_raw_parts(self.data, self.size as usize) } } @@ -525,7 +525,7 @@ impl BoxedRecordData { let (rtype, bytes) = (self.rtype, self.bytes()); // SAFETY: As documented on 'BoxedRecordData', the referenced bytes // are known to be a valid instance of the record data type (for all - // known record data types). As such, this function will succeed. + // known record data types). As such, this function will succeed. unsafe { RecordData::parse_record_data_bytes(bytes, rtype) .unwrap_unchecked() @@ -589,7 +589,7 @@ impl Drop for BoxedRecordData { ); // SAFETY: As documented on 'BoxedRecordData', 'data' and 'size' form - // the pointer and length of a 'Box<[u8]>'. Reconstructing the 'Box' + // the pointer and length of a 'Box<[u8]>'. Reconstructing the 'Box' // moves out of 'self', but this is sound because 'self' is dropped. let _ = unsafe { Box::from_raw(slice) }; } @@ -598,12 +598,12 @@ impl Drop for BoxedRecordData { //--- Send and Sync // SAFETY: 'BoxedRecordData' is equivalent to '(RType, Box<[u8]>)' with a -// custom representation. It cannot cause data races. +// custom representation. It cannot cause data races. #[cfg(feature = "alloc")] unsafe impl Send for BoxedRecordData {} // SAFETY: 'BoxedRecordData' is equivalent to '(RType, Box<[u8]>)' with a -// custom representation. It cannot cause data races. +// custom representation. It cannot cause data races. #[cfg(feature = "alloc")] unsafe impl Sync for BoxedRecordData {} @@ -619,7 +619,7 @@ impl From> for BoxedRecordData { /// serialized bytes cannot be parsed back into `RecordData<'_, &Name>`. fn from(value: RecordData<'_, N>) -> Self { // TODO: Determine the size of the record data upfront, and only - // allocate that much. Maybe as a new method on 'BuildBytes'... + // allocate that much. Maybe as a new method on 'BuildBytes'... let mut buffer = vec![0u8; 65535]; let rest_len = value .build_bytes(&mut buffer) @@ -736,7 +736,7 @@ impl BuildBytes for BoxedRecordData { /// Data for an unknown DNS record type. /// /// This is a fallback type, used for record types not known to the current -/// implementation. It must not be used for well-known record types, because +/// implementation. It must not be used for well-known record types, because /// some of them have special rules that this type does not follow. #[derive( Debug, PartialEq, Eq, Hash, AsBytes, BuildBytes, ParseBytesZC, UnsizedCopy, From 2f572b3c4bdaf5e2bc09204b633a5d2228a67eaf Mon Sep 17 00:00:00 2001 From: arya dradjica Date: Thu, 19 Feb 2026 11:15:57 +0100 Subject: [PATCH 4/6] [new/rdata] Fix minor typos --- src/new/rdata/basic/soa.rs | 4 ++-- src/new/rdata/edns.rs | 2 +- src/new/rdata/ipv6.rs | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/new/rdata/basic/soa.rs b/src/new/rdata/basic/soa.rs index 813436b65..7a77ca2ae 100644 --- a/src/new/rdata/basic/soa.rs +++ b/src/new/rdata/basic/soa.rs @@ -6,9 +6,9 @@ use crate::new::base::build::{BuildInMessage, NameCompressor}; use crate::new::base::name::CanonicalName; use crate::new::base::parse::{ParseMessageBytes, SplitMessageBytes}; use crate::new::base::{ - wire::*, ParseRecordData, ParseRecordDataBytes, RType, + wire::*, CanonicalRecordData, ParseRecordData, ParseRecordDataBytes, + RType, Serial, }; -use crate::new::base::{CanonicalRecordData, Serial}; //----------- Soa ------------------------------------------------------------ diff --git a/src/new/rdata/edns.rs b/src/new/rdata/edns.rs index f6b97630c..3cb4385f0 100644 --- a/src/new/rdata/edns.rs +++ b/src/new/rdata/edns.rs @@ -111,7 +111,7 @@ use crate::utils::dst::UnsizedCopy; /// /// As a DST, [`Opt`] does not implement [`Copy`] or [`Clone`]. Instead, it /// implements [`UnsizedCopy`]. An [`Opt`], held by reference, can be copied -/// into a different container (e.g. `Box`) using [`unsized_copy_into()`] +/// into a different container (e.g. `Box`) using [`unsized_copy_into()`]. /// /// [`unsized_copy_into()`]: UnsizedCopy::unsized_copy_into() /// diff --git a/src/new/rdata/ipv6.rs b/src/new/rdata/ipv6.rs index 4958e0a01..8ae29dc3e 100644 --- a/src/new/rdata/ipv6.rs +++ b/src/new/rdata/ipv6.rs @@ -24,10 +24,10 @@ use crate::utils::dst::UnsizedCopy; /// The IPv6 address of a host responsible for this domain. /// -/// A [`Aaaa`] record indicates that a domain name is backed by a server that -/// can be reached over the Internet at the specified IPv6 address. It does -/// not specify the server's capabilities (e.g. what protocols it supports); -/// those have to be communicated elsewhere. +/// A [`Aaaa`] ("quad-A") record indicates that a domain name is backed +/// by a server that can be reached over the Internet at the specified +/// IPv6 address. It does not specify the server's capabilities (e.g. what +/// protocols it supports); those have to be communicated elsewhere. /// /// [`Aaaa`] is specified by [RFC 3596, section 2]. It works identically to /// the [`A`] record. @@ -54,7 +54,7 @@ use crate::utils::dst::UnsizedCopy; /// /// [`RecordData`]: crate::new::rdata::RecordData /// -/// There's a few ways to build an [`Aaaa`]: +/// There's a few ways to build a [`Aaaa`]: /// /// ``` /// # use domain::new::base::wire::{ParseBytes, ParseBytesZC}; @@ -75,7 +75,7 @@ use crate::utils::dst::UnsizedCopy; /// let from_str: Aaaa = "2001:db8::".parse().unwrap(); /// # assert_eq!(from_raw, from_str); /// -/// // Parse a 'Aaaaa' from the DNS wire format. +/// // Parse a 'Aaaa' from the DNS wire format. /// let bytes = [0x20, 0x01, 0x0D, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; /// let from_wire: Aaaa = Aaaa::parse_bytes(&bytes).unwrap(); /// # assert_eq!(from_raw, from_wire); From a47fde778e9107ed4fea947dd053d9348da86823 Mon Sep 17 00:00:00 2001 From: arya dradjica Date: Mon, 16 Mar 2026 11:12:45 +0100 Subject: [PATCH 5/6] [new/rdata] Add 'Rp' --- src/new/base/record.rs | 7 +- src/new/rdata/mod.rs | 46 +++++--- src/new/rdata/rp.rs | 232 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+), 17 deletions(-) create mode 100644 src/new/rdata/rp.rs diff --git a/src/new/base/record.rs b/src/new/base/record.rs index bf9a6c762..a91474908 100644 --- a/src/new/base/record.rs +++ b/src/new/base/record.rs @@ -273,6 +273,9 @@ impl RType { /// The type of a [`Txt`](crate::new::rdata::Txt) record. pub const TXT: Self = Self::new(16); + /// The type of an [`Rp`](crate::new::rdata::Rp) record. + pub const RP: Self = Self::new(17); + /// The type of an [`Aaaa`](crate::new::rdata::Aaaa) record. pub const AAAA: Self = Self::new(28); @@ -324,7 +327,7 @@ impl RType { /// - [`PTR`](RType::PTR) /// - `MINFO` /// - [`MX`](RType::MX) - /// - `RP` + /// - [`RP`](RType::RP) /// - `AFSDB` /// - `RT` /// - `SIG` (obsolete) @@ -348,6 +351,7 @@ impl RType { | Self::SOA | Self::PTR | Self::MX + | Self::RP | Self::DNAME | Self::RRSIG ) @@ -383,6 +387,7 @@ impl fmt::Debug for RType { Self::HINFO => "RType::HINFO", Self::MX => "RType::MX", Self::TXT => "RType::TXT", + Self::RP => "RType::RP", Self::AAAA => "RType::AAAA", Self::DNAME => "RType::DNAME", Self::OPT => "RType::OPT", diff --git a/src/new/rdata/mod.rs b/src/new/rdata/mod.rs index 84d32895f..d66d37306 100644 --- a/src/new/rdata/mod.rs +++ b/src/new/rdata/mod.rs @@ -33,34 +33,36 @@ //! The following record data types are supported. They are enumerated by //! [`RecordData`], which can store any one of them at a time. //! -//! Basic record types (RFC 1035): -//! - [`A`] -//! - [`Ns`] -//! - [`CName`] +//! Core types: //! - [`Soa`] -//! - [`Ptr`] -//! - [`HInfo`] -//! - [`Mx`] -//! - [`Txt`] +//! - [`Ns`] //! -//! IPv6 support (RFC 3596): +//! Basic data types: +//! - [`A`] //! - [`Aaaa`] +//! - [`Mx`] +//! - [`Txt`] +//! - [`Rp`] //! -//! DNAME support (RFC 6672): +//! Indirection types: +//! - [`CName`] +//! - [`Ptr`] //! - [`DName`] //! -//! EDNS support (RFC 6891): -//! - [`Opt`] -//! -//! DNSSEC support (RFC 4034, RFC 5155): +//! Security related types: //! - [`DNSKey`] //! - [`RRSig`] //! - [`NSec`] //! - [`NSec3`] +//! - [`NSec3Param`] //! - [`Ds`] -//! -//! ZONEMD support (RFC 8976): //! - [`ZoneMD`] +//! +//! Miscellaneous types: +//! - [`HInfo`] +//! +//! "Pseudo-RR" types: +//! - [`Opt`] #![deny(missing_docs)] #![deny(clippy::missing_docs_in_private_items)] @@ -107,6 +109,9 @@ pub use ipv6::Aaaa; mod edns; pub use edns::{EdnsOptionsIter, Opt}; +mod rp; +pub use rp::Rp; + mod dnssec; pub use dnssec::{ DNSKey, DNSKeyFlags, DigestType, Ds, NSec, NSec3, NSec3Flags, @@ -269,6 +274,9 @@ define_record_data! { /// Free-form text strings about this domain. Txt(&'a Txt) = TXT, + /// Identification of the person/party responsible for this domain. + Rp(Rp) = RP, + /// The IPv6 address of a host responsible for this domain. Aaaa(Aaaa) = AAAA, @@ -318,6 +326,7 @@ impl<'a, N> RecordData<'a, N> { Self::HInfo(r) => RecordData::HInfo(r), Self::Mx(r) => RecordData::Mx(r.map_name(f)), Self::Txt(r) => RecordData::Txt(r), + Self::Rp(r) => RecordData::Rp(r.map_names(f)), Self::Aaaa(r) => RecordData::Aaaa(r), Self::DName(r) => RecordData::DName(r), Self::Opt(r) => RecordData::Opt(r), @@ -346,6 +355,7 @@ impl<'a, N> RecordData<'a, N> { Self::HInfo(r) => RecordData::HInfo(*r), Self::Mx(r) => RecordData::Mx(r.map_name_by_ref(f)), Self::Txt(r) => RecordData::Txt(r), + Self::Rp(r) => RecordData::Rp(r.map_names_by_ref(f)), Self::Aaaa(r) => RecordData::Aaaa(*r), Self::DName(r) => RecordData::DName(r), Self::Opt(r) => RecordData::Opt(r), @@ -380,6 +390,7 @@ impl<'a, N> RecordData<'a, N> { Self::HInfo(r) => RecordData::HInfo(r.clone_to_bump(bump)), Self::Mx(r) => RecordData::Mx(r.clone()), Self::Txt(r) => RecordData::Txt(copy_to_bump(*r, bump)), + Self::Rp(r) => RecordData::Rp(r.clone()), Self::Aaaa(r) => RecordData::Aaaa(*r), Self::DName(r) => RecordData::DName(copy_to_bump(*r, bump)), Self::Opt(r) => RecordData::Opt(copy_to_bump(*r, bump)), @@ -430,6 +441,9 @@ impl<'a, N: SplitMessageBytes<'a>> ParseRecordData<'a> for RecordData<'a, N> { RType::TXT => { <&Txt>::parse_bytes(&contents[start..]).map(Self::Txt) } + RType::RP => { + Rp::parse_message_bytes(contents, start).map(Self::Rp) + } RType::AAAA => { Aaaa::parse_bytes(&contents[start..]).map(Self::Aaaa) } diff --git a/src/new/rdata/rp.rs b/src/new/rdata/rp.rs new file mode 100644 index 000000000..8784a4162 --- /dev/null +++ b/src/new/rdata/rp.rs @@ -0,0 +1,232 @@ +//! The Responsible Person record data type. +//! +//! See [RFC 1183](https://datatracker.ietf.org/doc/html/rfc1183). + +use core::cmp::Ordering; + +use crate::new::base::build::{BuildInMessage, NameCompressor}; +use crate::new::base::name::CanonicalName; +use crate::new::base::parse::{ParseMessageBytes, SplitMessageBytes}; +use crate::new::base::{ + wire::*, CanonicalRecordData, ParseRecordData, ParseRecordDataBytes, + RType, +}; + +//----------- Rp ------------------------------------------------------------- + +/// Identification of the person/party responsible for this domain. +/// +/// An [`Rp`] record identifies the person or party managing a domain. It is +/// a useful backup when standard means of communication fail, e.g. e-mails to +/// `postmaster@` are being dropped due to mail server misconfiguration. +/// +/// [`Rp`] is specified by [RFC 1183, section 2]. +/// +/// [RFC 1183, section 2]: https://datatracker.ietf.org/doc/html/rfc1183#section-2 +/// +/// ## Wire Format +/// +/// The wire format of an [`Rp`] record is the concatenation of its fields, +/// in the same order as the `struct` definition. The domain names within an +/// [`Rp`] may be compressed in DNS messages. +/// +/// ## Usage +/// +/// Because [`Rp`] is a record data type, it is usually handled within an enum +/// like [`RecordData`]. This section describes how to use it independently +/// (or when building new record data from scratch). +/// +/// [`RecordData`]: crate::new::rdata::RecordData +/// +/// In order to build an [`Rp`], it's first important to choose a domain name +/// type. For short-term usage (where the [`Rp`] is a local variable), it is +/// common to pick [`RevNameBuf`]. If the [`Rp`] will be placed on the heap, +/// Box<[`RevName`]> will be more efficient. +/// +/// [`RevName`]: crate::new::base::name::RevName +/// [`RevNameBuf`]: crate::new::base::name::RevNameBuf +/// +/// The primary way to build a new [`Rp`] is to construct each field manually. +/// To parse a [`Rp`] from a DNS message, use [`ParseMessageBytes`]. In case +/// the input bytes don't use name compression, [`ParseBytes`] can be used. +/// +/// ``` +/// # use domain::new::base::name::{Name, RevNameBuf}; +/// # use domain::new::base::wire::{BuildBytes, ParseBytes, ParseBytesZC}; +/// # use domain::new::rdata::Rp; +/// # +/// // Build an 'Rp' manually: +/// let manual: Rp = Rp { +/// mailbox: "postmaster.example.org".parse().unwrap(), +/// texts: "findme.example.org".parse().unwrap(), +/// }; +/// +/// // Its wire format serialization looks like: +/// let bytes = b"\ +/// \x0Apostmaster\x07example\x03org\x00\ +/// \x06findme\x07example\x03org\x00"; +/// # let mut buffer = [0u8; 44]; +/// # manual.build_bytes(&mut buffer).unwrap(); +/// # assert_eq!(*bytes, buffer); +/// +/// // Parse an 'Rp' from the wire format, without name decompression: +/// let from_wire: Rp = Rp::parse_bytes(bytes).unwrap(); +/// # assert_eq!(manual, from_wire); +/// +/// // See 'ParseMessageBytes' for parsing with name decompression. +/// ``` +/// +/// Since [`Rp`] is a sized type, and it implements [`Copy`] and [`Clone`], +/// it's straightforward to handle and move around. However, this depends +/// on the domain name type. It can be changed using [`Rp::map_names()`] and +/// [`Rp::map_names_by_ref()`]. +/// +/// For debugging, [`Rp`] can be formatted using [`fmt::Debug`]. +/// +/// [`fmt::Debug`]: core::fmt::Debug +/// +/// To serialize an [`Rp`] in the wire format, use [`BuildInMessage`] (which +/// supports name compression). If name compression is not desired, use +/// [`BuildBytes`]. +#[derive( + Copy, + Clone, + Debug, + PartialEq, + Eq, + Hash, + BuildBytes, + ParseBytes, + SplitBytes, +)] +pub struct Rp { + /// The mailbox of the responsible person/party. + /// + /// This address should lie outside the domain, so that it can be used if + /// the domain is malfunctioning. It can be used to communicate with the + /// responsible person/party, similar to the conventional `postmaster@` + /// address. + /// + /// The first label here is the username (i.e. local part) of the e-mail + /// address, and the remaining labels make up the mail domain name. For + /// example, would be represented as + /// `hostmaster.sri-nic.arpa`. This convention is specified in [RFC 1034, + /// section 3.3]. + /// + /// [RFC 1034, section 3.3]: https://datatracker.ietf.org/doc/html/rfc1034#section-3.3 + /// + /// This is an optional field; if this field refers to the root domain + /// (`.`), no mailbox is available. + pub mailbox: N, + + /// A domain providing [`Txt`] records for human inspection. + /// + /// [`Txt`]: crate::new::rdata::Txt + /// + /// This should lie outside the name owning the record, so that it can be + /// used if the domain is malfunctioning. The referenced domain should + /// provide human-readable [`Txt`] records which explain how to reach the + /// responsible person/party. + /// + /// This is an optional field; if this field refers to the root domain + /// (`.`), no domain is available. + pub texts: N, +} + +//--- Interaction + +impl Rp { + /// Map the domain names within to another type. + pub fn map_names R>(self, mut f: F) -> Rp { + Rp { + mailbox: (f)(self.mailbox), + texts: (f)(self.texts), + } + } + + /// Map references to the domain names within to another type. + pub fn map_names_by_ref<'r, R, F: FnMut(&'r N) -> R>( + &'r self, + mut f: F, + ) -> Rp { + Rp { + mailbox: (f)(&self.mailbox), + texts: (f)(&self.texts), + } + } +} + +//--- Canonical operations + +impl CanonicalRecordData for Rp { + fn build_canonical_bytes<'b>( + &self, + bytes: &'b mut [u8], + ) -> Result<&'b mut [u8], TruncationError> { + let bytes = self.mailbox.build_lowercased_bytes(bytes)?; + let bytes = self.texts.build_lowercased_bytes(bytes)?; + Ok(bytes) + } + + fn cmp_canonical(&self, other: &Self) -> Ordering { + self.mailbox + .cmp_lowercase_composed(&other.mailbox) + .then_with(|| self.texts.cmp_lowercase_composed(&other.texts)) + } +} + +//--- Parsing from DNS messages + +impl<'a, N: SplitMessageBytes<'a>> ParseMessageBytes<'a> for Rp { + fn parse_message_bytes( + contents: &'a [u8], + start: usize, + ) -> Result { + let (mailbox, rest) = N::split_message_bytes(contents, start)?; + let texts = N::parse_message_bytes(contents, rest)?; + + Ok(Self { mailbox, texts }) + } +} + +//--- Building into DNS messages + +impl BuildInMessage for Rp { + fn build_in_message( + &self, + contents: &mut [u8], + mut start: usize, + compressor: &mut NameCompressor, + ) -> Result { + start = self.mailbox.build_in_message(contents, start, compressor)?; + start = self.texts.build_in_message(contents, start, compressor)?; + Ok(start) + } +} + +//--- Parsing record data + +impl<'a, N: SplitMessageBytes<'a>> ParseRecordData<'a> for Rp { + fn parse_record_data( + contents: &'a [u8], + start: usize, + rtype: RType, + ) -> Result { + match rtype { + RType::RP => Self::parse_message_bytes(contents, start), + _ => Err(ParseError), + } + } +} + +impl<'a, N: SplitBytes<'a>> ParseRecordDataBytes<'a> for Rp { + fn parse_record_data_bytes( + bytes: &'a [u8], + rtype: RType, + ) -> Result { + match rtype { + RType::RP => Self::parse_bytes(bytes), + _ => Err(ParseError), + } + } +} From 82866a32eb4dad5658cb0297ccb18a64cdd2c9c6 Mon Sep 17 00:00:00 2001 From: arya dradjica Date: Fri, 20 Mar 2026 16:08:35 +0100 Subject: [PATCH 6/6] [new/base] Expand 'QType' and 'RType' --- src/new/base/question.rs | 76 ++++++++++++++++++++++++++++++++++++++++ src/new/base/record.rs | 12 +++++++ 2 files changed, 88 insertions(+) diff --git a/src/new/base/question.rs b/src/new/base/question.rs index 4d1f10ae4..5bd9ec834 100644 --- a/src/new/base/question.rs +++ b/src/new/base/question.rs @@ -182,13 +182,74 @@ impl QType { /// The type of queries for [`Txt`](crate::new::rdata::Txt) records. pub const TXT: Self = Self::new(16); + /// The type of queries for [`Rp`](crate::new::rdata::Rp) records. + pub const RP: Self = Self::new(17); + /// The type of queries for [`Aaaa`](crate::new::rdata::Aaaa) records. pub const AAAA: Self = Self::new(28); + /// The type of queries for [`DName`](crate::new::rdata::DName) records. + pub const DNAME: Self = Self::new(39); + + /// The type of queries for [`Opt`](crate::new::rdata::Opt) records. + pub const OPT: Self = Self::new(41); + + /// The type of queries for [`Ds`](crate::new::rdata::Ds) records. + pub const DS: Self = Self::new(43); + + /// The type of queries for [`RRSig`](crate::new::rdata::RRSig) records. + pub const RRSIG: Self = Self::new(46); + + /// The type of queries for [`NSec`](crate::new::rdata::NSec) records. + pub const NSEC: Self = Self::new(47); + + /// The type of queries for [`DNSKey`](crate::new::rdata::DNSKey) records. + pub const DNSKEY: Self = Self::new(48); + + /// The type of queries for [`NSec3`](crate::new::rdata::NSec3) records. + pub const NSEC3: Self = Self::new(50); + + /// The type of queries for [`NSec3Param`](crate::new::rdata::NSec3Param) records. + pub const NSEC3PARAM: Self = Self::new(51); + + /// The type of querios for `Cds` records. + pub const CDS: Self = Self::new(59); + + /// The type of querios for `CDNSKey` records. + pub const CDNSKEY: Self = Self::new(60); + + /// The type of querios for [`ZoneMD`](crate::new::rdata::ZoneMD) records. + pub const ZONEMD: Self = Self::new(63); + + /// The type of querios for `TSig` records. + pub const TSIG: Self = Self::new(250); + + /// The type of requests for incremental zone transfers (IXFRs). + pub const IXFR: Self = Self::new(251); + + /// The type of requests for authoritative zone transfers (AXFRs). + pub const AXFR: Self = Self::new(252); + /// The type of queries for all available records. pub const ANY: Self = Self::new(255); } +//--- Conversion to and from 'u16' + +impl From for QType { + fn from(value: u16) -> Self { + Self { + code: U16::new(value), + } + } +} + +impl From for u16 { + fn from(value: QType) -> Self { + value.code.get() + } +} + //--- Formatting impl fmt::Debug for QType { @@ -202,7 +263,22 @@ impl fmt::Debug for QType { Self::HINFO => "QType::HINFO", Self::MX => "QType::MX", Self::TXT => "QType::TXT", + Self::RP => "QType::RP", Self::AAAA => "QType::AAAA", + Self::DNAME => "QType::DNAME", + Self::OPT => "QType::OPT", + Self::DS => "QType::DS", + Self::RRSIG => "QType::RRSIG", + Self::NSEC => "QType::NSEC", + Self::DNSKEY => "QType::DNSKEY", + Self::NSEC3 => "QType::NSEC3", + Self::NSEC3PARAM => "QType::NSEC3PARAM", + Self::CDS => "QType::CDS", + Self::CDNSKEY => "QType::CDNSKEY", + Self::ZONEMD => "QType::ZONEMD", + Self::TSIG => "QType::TSIG", + Self::IXFR => "QType::IXFR", + Self::AXFR => "QType::AXFR", Self::ANY => "QType::ANY", _ => return write!(f, "QType({})", self.code), }) diff --git a/src/new/base/record.rs b/src/new/base/record.rs index a91474908..8c9bceb29 100644 --- a/src/new/base/record.rs +++ b/src/new/base/record.rs @@ -303,8 +303,17 @@ impl RType { /// The type of an [`NSec3Param`](crate::new::rdata::NSec3Param) record. pub const NSEC3PARAM: Self = Self::new(51); + /// The type of a `Cds` record. + pub const CDS: Self = Self::new(59); + + /// The type of a `CDNSKey` record. + pub const CDNSKEY: Self = Self::new(60); + /// The type of a [`ZoneMD`](crate::new::rdata::ZoneMD) record. pub const ZONEMD: Self = Self::new(63); + + /// The type of a `TSig` record. + pub const TSIG: Self = Self::new(250); } //--- Interaction @@ -397,7 +406,10 @@ impl fmt::Debug for RType { Self::DNSKEY => "RType::DNSKEY", Self::NSEC3 => "RType::NSEC3", Self::NSEC3PARAM => "RType::NSEC3PARAM", + Self::CDS => "RType::CDS", + Self::CDNSKEY => "RType::CDNSKEY", Self::ZONEMD => "RType::ZONEMD", + Self::TSIG => "RType::TSIG", _ => return write!(f, "RType({})", self.code), }) }