diff --git a/src/base/name/dname.rs b/src/base/name/dname.rs index 12f9eafa5..9610f4cab 100644 --- a/src/base/name/dname.rs +++ b/src/base/name/dname.rs @@ -7,6 +7,7 @@ use super::super::octets::{ use super::super::octets::{DeserializeOctets, SerializeOctets}; use super::builder::{DnameBuilder, FromStrError}; use super::label::{Label, LabelTypeError, SplitLabelError}; +use super::parsed::ParsedDname; use super::relative::{DnameIter, RelativeDname}; use super::traits::{ToDname, ToLabelIter}; #[cfg(feature = "master")] @@ -624,6 +625,17 @@ where } } +impl OctetsFrom> for Dname +where + SrcOctets: AsRef<[u8]>, + Octets: FromBuilder, + ::Builder: EmptyBuilder, +{ + fn octets_from(source: ParsedDname) -> Result { + source.to_dname().map_err(|_| ShortBuf) + } +} + //--- FromStr impl FromStr for Dname diff --git a/src/base/octets.rs b/src/base/octets.rs index e0255ed3e..28733a763 100644 --- a/src/base/octets.rs +++ b/src/base/octets.rs @@ -371,32 +371,16 @@ impl<'a, Source: AsRef<[u8]> + 'a> OctetsFrom<&'a Source> for &'a [u8] { } #[cfg(feature = "std")] -impl OctetsFrom for Vec -where - Self: From, -{ - fn octets_from(source: Source) -> Result { - Ok(From::from(source)) +impl<'a> OctetsFrom<&'a [u8]> for Vec { + fn octets_from(source: &'a [u8]) -> Result { + Ok(Self::from(source)) } } -#[cfg(feature = "bytes")] -impl OctetsFrom for Bytes -where - Self: From, -{ - fn octets_from(source: Source) -> Result { - Ok(From::from(source)) - } -} - -#[cfg(feature = "bytes")] -impl OctetsFrom for BytesMut -where - Self: From, -{ - fn octets_from(source: Source) -> Result { - Ok(From::from(source)) +#[cfg(feature = "std")] +impl OctetsFrom> for Vec { + fn octets_from(source: Vec) -> Result { + Ok(source) } } @@ -411,6 +395,76 @@ where } } +#[cfg(feature = "bytes")] +impl<'a> OctetsFrom<&'a [u8]> for Bytes { + fn octets_from(source: &'a [u8]) -> Result { + Ok(Self::copy_from_slice(source)) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for Bytes { + fn octets_from(source: Bytes) -> Result { + Ok(source) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for BytesMut { + fn octets_from(source: BytesMut) -> Result { + Ok(source) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for BytesMut { + fn octets_from(source: Bytes) -> Result { + Ok(Self::from(source.as_ref())) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for Bytes { + fn octets_from(source: BytesMut) -> Result { + Ok(Self::from(source)) + } +} + +#[cfg(feature = "bytes")] +impl<'a> OctetsFrom<&'a [u8]> for BytesMut { + fn octets_from(source: &'a [u8]) -> Result { + Ok(Self::from(source)) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom> for Bytes { + fn octets_from(source: Vec) -> Result { + Ok(Self::from(source)) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom> for BytesMut { + fn octets_from(source: Vec) -> Result { + Ok(Self::from(source.as_slice())) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for Vec { + fn octets_from(source: Bytes) -> Result { + Ok(source.as_ref().to_vec()) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for Vec { + fn octets_from(source: BytesMut) -> Result { + Ok(source.as_ref().to_vec()) + } +} + #[cfg(feature = "heapless")] impl OctetsFrom for heapless::Vec where @@ -1884,6 +1938,41 @@ macro_rules! octets_array { } } + impl OctetsFrom<$name> for $name { + fn octets_from(source: $name) -> Result { + Ok(source) + } + } + + #[cfg(feature = "std")] + impl OctetsFrom> for $name { + fn octets_from(source: Vec) -> Result { + let octets = <[u8; $len]>::try_from(source).map_err(|_| ShortBuf)?; + Ok($name { octets, len: $len }) + } + } + + #[cfg(feature = "std")] + impl OctetsFrom<$name> for Vec { + fn octets_from(source: $name) -> Result { + Ok(source.octets.into()) + } + } + + #[cfg(feature = "bytes")] + impl OctetsFrom<$name> for Bytes { + fn octets_from(source: $name) -> Result { + Ok(source.octets.to_vec().into()) + } + } + + #[cfg(feature = "bytes")] + impl OctetsFrom<$name> for BytesMut { + fn octets_from(source: $name) -> Result { + Ok(BytesMut::from(source.octets.as_ref())) + } + } + impl core::ops::Deref for $name { type Target = [u8]; @@ -2260,4 +2349,61 @@ mod test { assert_eq!(parser.parse_u32(), Ok(0xfd78a84e)); assert_eq!(parser.parse_u32(), Err(ParseError::ShortInput)); } + + #[cfg(feature = "std")] + #[test] + fn convert() { + use crate::base::octets::{Octets32, OctetsInto}; + use crate::base::{Dname, Record}; + use crate::rdata::Cname; + + // Use case: provide a flexible interface for caller to + // get record from storage. + fn load_record() -> Record, Cname>> + where + O: FromBuilder + OctetsFrom, + ::Builder: EmptyBuilder, + { + // let rr = cache_get().clone(); + let rr: Record, Cname>> = ( + "a.example".parse().unwrap(), + 300, + Cname::new("b.example".parse().unwrap()), + ) + .into(); + + rr.octets_into().unwrap() + } + let rr: Record>, Cname>>> = load_record(); + + let rr_ref: Record<_, _> = ( + rr.owner().for_slice(), + rr.ttl(), + Cname::new(rr.data().cname().for_slice()), + ) + .into(); + + // Use case: save a owned copy into cache. + fn save_record(rr: Record, Cname>>) + where + O: AsRef<[u8]>, + Vec: OctetsFrom, + { + let _owned: Record>, Cname>>> = + rr.octets_into().unwrap(); + // cache_put(_owned) + } + save_record(rr_ref.clone()); + + // convert between octets + #[cfg(feature = "bytes")] + { + use bytes::Bytes; + + let b: Record, Cname>> = + rr_ref.clone().octets_into().unwrap(); + let _: Record>, Cname>>> = + b.octets_into().unwrap(); + } + } } diff --git a/src/base/record.rs b/src/base/record.rs index 90ee5b307..a772908ee 100644 --- a/src/base/record.rs +++ b/src/base/record.rs @@ -1007,22 +1007,24 @@ impl From for RecordParseError { mod test { #[test] - #[cfg(features = "bytes")] + #[cfg(feature = "bytes")] fn ds_octets_into() { - use crate::base::iana::{DigestAlg, Rtype, SecAlg}; - use crate::name::Dname; - use crate::octets::OctetsInto; + use crate::base::iana::{Class, DigestAlg, SecAlg}; + use crate::base::octets::OctetsInto; + use crate::base::{Dname, Record}; use crate::rdata::Ds; + use bytes::Bytes; + let owner = "a.example".parse::>().unwrap(); let ds: Record, Ds<&[u8]>> = Record::new( - "a.example".parse().unwrap(), + owner.for_slice(), Class::In, 86400, - Ds::new(12, SecAlg::RsaSha256, b"something"), + Ds::new(12, SecAlg::RsaSha256, DigestAlg::Sha256, b"something"), ); let ds_bytes: Record, Ds> = - ds.octets_into().unwrap(); + ds.clone().octets_into().unwrap(); assert_eq!(ds.owner(), ds_bytes.owner()); - asswer_eq!(ds.data().digest(), ds_bytes.data().digest()); + assert_eq!(ds.data().digest(), ds_bytes.data().digest()); } } diff --git a/src/rdata/rfc1035.rs b/src/rdata/rfc1035.rs index afcfe90fe..5e987fda2 100644 --- a/src/rdata/rfc1035.rs +++ b/src/rdata/rfc1035.rs @@ -1841,29 +1841,30 @@ mod test { use std::vec::Vec; #[test] - #[cfg(features = "bytes")] + #[cfg(feature = "bytes")] fn hinfo_octets_into() { - use crate::octets::OctetsInto; + use crate::base::octets::OctetsInto; let hinfo: Hinfo> = Hinfo::new("1234".parse().unwrap(), "abcd".parse().unwrap()); - let hinfo_bytes: Hinfo = hinfo.octets_into().unwrap(); + let hinfo_bytes: Hinfo = + hinfo.clone().octets_into().unwrap(); assert_eq!(hinfo.cpu(), hinfo_bytes.cpu()); assert_eq!(hinfo.os(), hinfo_bytes.os()); } #[test] - #[cfg(features = "bytes")] + #[cfg(feature = "bytes")] fn minfo_octets_into() { + use crate::base::octets::OctetsInto; use crate::base::Dname; - use crate::octets::OctetsInto; let minfo: Minfo>> = Minfo::new( "a.example".parse().unwrap(), "b.example".parse().unwrap(), ); let minfo_bytes: Minfo> = - minfo.octets_into().unwrap(); + minfo.clone().octets_into().unwrap(); assert_eq!(minfo.rmailbx(), minfo_bytes.rmailbx()); assert_eq!(minfo.emailbx(), minfo_bytes.emailbx()); }