diff --git a/crates/client/src/error/dnssec_error.rs b/crates/client/src/error/dnssec_error.rs index 518117681c..a6653a9c8f 100644 --- a/crates/client/src/error/dnssec_error.rs +++ b/crates/client/src/error/dnssec_error.rs @@ -161,7 +161,7 @@ impl From for Error { pub mod not_openssl { use std; - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] pub struct SslErrorStack; impl std::fmt::Display for SslErrorStack { @@ -181,10 +181,10 @@ pub mod not_openssl { pub mod not_ring { use std; - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] pub struct KeyRejected; - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] pub struct Unspecified; impl std::fmt::Display for KeyRejected { diff --git a/crates/proto/src/error.rs b/crates/proto/src/error.rs index b9fbb02ec3..751b20de18 100644 --- a/crates/proto/src/error.rs +++ b/crates/proto/src/error.rs @@ -332,7 +332,7 @@ pub mod not_openssl { use std; /// SslErrorStac stub - #[derive(Debug)] + #[derive(Debug, Clone, Copy)] pub struct SslErrorStack; impl std::fmt::Display for SslErrorStack { @@ -354,7 +354,7 @@ pub mod not_ring { use std; /// The Unspecified error replacement - #[derive(Debug)] + #[derive(Debug, Copy, Clone)] pub struct Unspecified; impl std::fmt::Display for Unspecified { diff --git a/crates/proto/src/lib.rs b/crates/proto/src/lib.rs index de7bab10d0..91102f9366 100644 --- a/crates/proto/src/lib.rs +++ b/crates/proto/src/lib.rs @@ -8,6 +8,7 @@ #![warn( missing_docs, + missing_copy_implementations, clippy::dbg_macro, clippy::print_stdout, clippy::unimplemented @@ -194,6 +195,7 @@ pub trait Time { /// New type which is implemented using tokio::time::{Delay, Timeout} #[cfg(any(test, feature = "tokio-runtime"))] +#[derive(Debug, Clone, Copy)] pub struct TokioTime; #[cfg(any(test, feature = "tokio-runtime"))] diff --git a/crates/proto/src/op/header.rs b/crates/proto/src/op/header.rs index 7144227fbb..cf7448ad31 100644 --- a/crates/proto/src/op/header.rs +++ b/crates/proto/src/op/header.rs @@ -55,7 +55,7 @@ use crate::serialize::binary::*; /// /// ``` /// -#[derive(Clone, Debug, PartialEq, PartialOrd)] +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] pub struct Header { id: u16, message_type: MessageType, diff --git a/crates/proto/src/op/message.rs b/crates/proto/src/op/message.rs index 2d8f625a67..5743d74318 100644 --- a/crates/proto/src/op/message.rs +++ b/crates/proto/src/op/message.rs @@ -95,7 +95,8 @@ pub fn update_header_counts( assert!(counts.nameserver_count <= u16::max_value() as usize); assert!(counts.additional_count <= u16::max_value() as usize); - let mut header = current_header.clone(); + // TODO: should the function just take by value? + let mut header = *current_header; header .set_query_count(counts.query_count as u16) .set_answer_count(counts.answer_count as u16) @@ -109,6 +110,7 @@ pub fn update_header_counts( /// Tracks the counts of the records in the Message. /// /// This is only used internally during serialization. +#[derive(Debug, Copy, Clone)] pub struct HeaderCounts { /// The number of queries in the Message pub query_count: usize, @@ -678,6 +680,58 @@ impl Message { Ok(()) } + + /// Consumes `Message` and returns into components + pub fn into_parts(self) -> MessageParts { + self.into() + } +} + +/// Consumes `Message` giving public access to fields in `Message` so they can be +/// destructured and taken by value +/// ```rust +/// let msg = Message::new(); +/// let MessageParts { queries, .. } = msg.into_parts(); +/// ``` +#[derive(Clone, Debug, PartialEq, Default)] +pub struct MessageParts { + /// message header + pub header: Header, + /// message queries + pub queries: Vec, + /// message answers + pub answers: Vec, + /// message name_servers + pub name_servers: Vec, + /// message additional records + pub additionals: Vec, + /// sig0 + pub sig0: Vec, + /// optional edns records + pub edns: Option, +} + +impl From for MessageParts { + fn from(msg: Message) -> Self { + let Message { + header, + queries, + answers, + name_servers, + additionals, + sig0, + edns, + } = msg; + MessageParts { + header, + queries, + answers, + name_servers, + additionals, + sig0, + edns, + } + } } impl Deref for Message { @@ -709,6 +763,7 @@ pub trait MessageFinalizer: Send + Sync + 'static { /// A MessageFinalizer which does nothing /// /// *WARNING* This should only be used in None context, it will panic in all cases where finalize is called. +#[derive(Debug, Clone, Copy)] pub struct NoopMessageFinalizer; impl NoopMessageFinalizer { diff --git a/crates/proto/src/op/query.rs b/crates/proto/src/op/query.rs index e105b804ea..cc3f229eac 100644 --- a/crates/proto/src/op/query.rs +++ b/crates/proto/src/op/query.rs @@ -159,6 +159,55 @@ impl Query { pub fn mdns_unicast_response(&self) -> bool { self.mdns_unicast_response } + + /// Consumes `Query` and returns it's components + pub fn into_parts(self) -> QueryParts { + self.into() + } +} + +/// Consumes `Query` giving public access to fields of `Query` so they can +/// be destructured and taken by value. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct QueryParts { + /// QNAME + pub name: Name, + /// QTYPE + pub query_type: RecordType, + /// QCLASS + pub query_class: DNSClass, + /// mDNS unicast-response bit set or not + #[cfg(feature = "mdns")] + pub mdns_unicast_response: bool, +} + +impl From for QueryParts { + fn from(q: Query) -> Self { + cfg_if::cfg_if! { + if #[cfg(feature = "mdns")] { + let Query { + name, + query_type, + query_class, + mdns_unicast_response, + } = q; + } else { + let Query { + name, + query_type, + query_class, + } = q; + } + } + + Self { + name, + query_type, + query_class, + #[cfg(feature = "mdns")] + mdns_unicast_response, + } + } } impl BinEncodable for Query { diff --git a/crates/proto/src/rr/dnssec/ec_public_key.rs b/crates/proto/src/rr/dnssec/ec_public_key.rs index af872d65ab..c5542adf8b 100644 --- a/crates/proto/src/rr/dnssec/ec_public_key.rs +++ b/crates/proto/src/rr/dnssec/ec_public_key.rs @@ -8,6 +8,7 @@ use super::Algorithm; use crate::error::*; +#[derive(Copy, Clone)] pub struct ECPublicKey { buf: [u8; MAX_LEN], len: usize, diff --git a/crates/proto/src/rr/dnssec/mod.rs b/crates/proto/src/rr/dnssec/mod.rs index ba0b484776..701e30155e 100644 --- a/crates/proto/src/rr/dnssec/mod.rs +++ b/crates/proto/src/rr/dnssec/mod.rs @@ -49,6 +49,7 @@ pub use ring::digest::Digest; /// This is an empty type, enable Ring or OpenSSL for this feature #[cfg(not(any(feature = "openssl", feature = "ring")))] +#[derive(Copy, Clone, Debug)] pub struct Digest; #[cfg(not(any(feature = "openssl", feature = "ring")))] diff --git a/crates/proto/src/rr/rdata/opt.rs b/crates/proto/src/rr/rdata/opt.rs index 153e5f2bdf..f17ae8d795 100644 --- a/crates/proto/src/rr/rdata/opt.rs +++ b/crates/proto/src/rr/rdata/opt.rs @@ -181,6 +181,7 @@ impl OPT { OPT { options } } + #[deprecated(note = "Please use as_ref() or as_mut() for shared/mutable references")] /// The entire map of options pub fn options(&self) -> &HashMap { &self.options @@ -202,6 +203,18 @@ impl OPT { } } +impl AsMut> for OPT { + fn as_mut(&mut self) -> &mut HashMap { + &mut self.options + } +} + +impl AsRef> for OPT { + fn as_ref(&self) -> &HashMap { + &self.options + } +} + /// Read the RData from the given Decoder pub fn read(decoder: &mut BinDecoder<'_>, rdata_length: Restrict) -> ProtoResult { let mut state: OptReadState = OptReadState::ReadCode; @@ -277,7 +290,7 @@ pub fn read(decoder: &mut BinDecoder<'_>, rdata_length: Restrict) -> ProtoR /// Write the RData from the given Decoder pub fn emit(encoder: &mut BinEncoder<'_>, opt: &OPT) -> ProtoResult<()> { - for (edns_code, edns_option) in opt.options().iter() { + for (edns_code, edns_option) in opt.as_ref().iter() { encoder.emit_u16(u16::from(*edns_code))?; encoder.emit_u16(edns_option.len())?; edns_option.emit(encoder)? diff --git a/crates/proto/src/rr/resource.rs b/crates/proto/src/rr/resource.rs index 0b3a7af534..ee420d5b42 100644 --- a/crates/proto/src/rr/resource.rs +++ b/crates/proto/src/rr/resource.rs @@ -264,6 +264,64 @@ impl Record { pub fn into_data(self) -> RData { self.rdata } + + /// Consumes `Record` and returns its components + pub fn into_parts(self) -> RecordParts { + self.into() + } +} + +/// Consumes `Record` giving public access to fields of `Record` so they can +/// be destructured and taken by value +pub struct RecordParts { + /// label names + pub name_labels: Name, + /// record type + pub rr_type: RecordType, + /// dns class + pub dns_class: DNSClass, + /// time to live + pub ttl: u32, + /// rdata + pub rdata: RData, + /// mDNS cache flush + #[cfg(feature = "mdns")] + pub mdns_cache_flush: bool, +} + +impl From for RecordParts { + fn from(record: Record) -> Self { + cfg_if::cfg_if! { + if #[cfg(feature = "mdns")] { + let Record { + name_labels, + rr_type, + dns_class, + ttl, + rdata, + mdns_cache_flush, + } = record; + } else { + let Record { + name_labels, + rr_type, + dns_class, + ttl, + rdata, + } = record; + } + } + + RecordParts { + name_labels, + rr_type, + dns_class, + ttl, + rdata, + #[cfg(feature = "mdns")] + mdns_cache_flush, + } + } } #[allow(deprecated)] diff --git a/crates/proto/src/rr/rr_set.rs b/crates/proto/src/rr/rr_set.rs index 4ce3d6cfb9..59e18d8b4e 100644 --- a/crates/proto/src/rr/rr_set.rs +++ b/crates/proto/src/rr/rr_set.rs @@ -431,6 +431,47 @@ impl RecordSet { removed } + + /// Consumes `RecordSet` and returns its components + pub fn into_parts(self) -> RecordSetParts { + self.into() + } +} + +/// Consumes `RecordSet` giving public access to fields of `RecordSet` so they can +/// be destructured and taken by value +#[derive(Clone, Debug, PartialEq)] +pub struct RecordSetParts { + pub name: Name, + pub record_type: RecordType, + pub dns_class: DNSClass, + pub ttl: u32, + pub records: Vec, + pub rrsigs: Vec, + pub serial: u32, // serial number at which this record was modifie, +} + +impl From for RecordSetParts { + fn from(rset: RecordSet) -> Self { + let RecordSet { + name, + record_type, + dns_class, + ttl, + records, + rrsigs, + serial, + } = rset; + RecordSetParts { + name, + record_type, + dns_class, + ttl, + records, + rrsigs, + serial, + } + } } impl From for RecordSet { diff --git a/crates/proto/src/xfer/dns_request.rs b/crates/proto/src/xfer/dns_request.rs index a0a7f6af3b..29ed6b045d 100644 --- a/crates/proto/src/xfer/dns_request.rs +++ b/crates/proto/src/xfer/dns_request.rs @@ -12,7 +12,7 @@ use std::ops::{Deref, DerefMut}; use crate::op::Message; /// A set of options for expressing options to how requests should be treated -#[derive(Clone, Default)] +#[derive(Clone, Copy, Debug, Default)] pub struct DnsRequestOptions { /// When true, the underlying DNS protocols will not return on the first response received. /// diff --git a/crates/proto/src/xfer/dns_response.rs b/crates/proto/src/xfer/dns_response.rs index c7838b983c..e547337111 100644 --- a/crates/proto/src/xfer/dns_response.rs +++ b/crates/proto/src/xfer/dns_response.rs @@ -443,7 +443,7 @@ impl From> for DnsResponse { /// NXT and SIG records MUST be added. /// /// ``` -#[derive(Eq, PartialEq, Debug)] +#[derive(Eq, PartialEq, Debug, Clone, Copy)] pub enum NegativeType { /// ```text /// NXDOMAIN RESPONSE: TYPE 1. diff --git a/crates/resolver/src/caching_client.rs b/crates/resolver/src/caching_client.rs index 4a87ca08ed..6c706fa427 100644 --- a/crates/resolver/src/caching_client.rs +++ b/crates/resolver/src/caching_client.rs @@ -177,7 +177,7 @@ where let response_message = client .client - .lookup(query.clone(), options.clone()) + .lookup(query.clone(), options) .await .map_err(E::into); diff --git a/crates/resolver/src/lookup.rs b/crates/resolver/src/lookup.rs index 6762edc9bb..d1de342562 100644 --- a/crates/resolver/src/lookup.rs +++ b/crates/resolver/src/lookup.rs @@ -245,7 +245,7 @@ where let query: Pin> + Send>> = match name { Ok(name) => client_cache - .lookup(Query::query(name, record_type), options.clone()) + .lookup(Query::query(name, record_type), options) .boxed(), Err(err) => future::err(err).boxed(), }; @@ -287,7 +287,7 @@ where if should_retry { if let Some(name) = self.names.pop() { let record_type = self.record_type; - let options = self.options.clone(); + let options = self.options; // If there's another name left to try, build a new query // for that next name and continue looping. diff --git a/crates/resolver/src/lookup_ip.rs b/crates/resolver/src/lookup_ip.rs index 26f4e33f42..db65eb2fdd 100644 --- a/crates/resolver/src/lookup_ip.rs +++ b/crates/resolver/src/lookup_ip.rs @@ -166,7 +166,7 @@ where name, self.strategy, self.client_cache.clone(), - self.options.clone(), + self.options, self.hosts.clone(), ) .boxed(); @@ -315,7 +315,7 @@ where hosts_lookup( Query::query(name.clone(), RecordType::A), client.clone(), - options.clone(), + options, hosts.clone(), ) .boxed(), @@ -414,7 +414,7 @@ where let res = hosts_lookup( Query::query(name.clone(), first_type), client, - options.clone(), + options, hosts.clone(), ) .await;