mirror of
https://github.com/NLnetLabs/domain.git
synced 2026-09-30 13:44:59 +02:00
Allow ?Sized where appropriate. (#168)
This commit adds a ?Sized trait bound to all types that exclusively wrap an
octets sequence. In the process, it also does some cleanup here and there to
improve consistency of the crate.
Specifically, it includes the following noteworthy changes:
o All types that wrap an octets sequence only allow unsized octets
sequence types. They all have an associated function from_slice to
create a reference to a value wrapping an (unsized) octets slice and
method for_slice that converts a &self into such a reference. Where
the latter already existed but returned a value wrapping a &[u8]
(e.g., Dname<_> and Message<_>, the return type has changed
accordingly.
o Removed CharStr::from_bytes. Use CharStr::from_octets instead.
o Message::from_octets now returns a new error type ShortMessage.
o Dropped Deref impls for Dname<_>, RelativeDname<_>.
o Renamed opt::KeyTag::new to opt::KeyTag::from_octets.
o Renamed rdata::Txt::try_from_slice to build_from_slice.
This commit is contained in:
+73
-67
@@ -27,7 +27,7 @@ use super::cmp::CanonicalOrd;
|
||||
use super::scan::{BadSymbol, Scanner, Symbol, SymbolCharsError};
|
||||
use super::wire::{Compose, ParseError};
|
||||
#[cfg(feature = "bytes")]
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use bytes::BytesMut;
|
||||
use core::{cmp, fmt, hash, ops, str};
|
||||
use octseq::builder::FreezeBuilder;
|
||||
#[cfg(feature = "serde")]
|
||||
@@ -72,11 +72,8 @@ impl<Octs: ?Sized> CharStr<Octs> {
|
||||
where
|
||||
Octs: AsRef<[u8]> + Sized,
|
||||
{
|
||||
if octets.as_ref().len() > 255 {
|
||||
Err(CharStrError)
|
||||
} else {
|
||||
Ok(unsafe { Self::from_octets_unchecked(octets) })
|
||||
}
|
||||
CharStr::check_slice(octets.as_ref())?;
|
||||
Ok(unsafe { Self::from_octets_unchecked(octets) })
|
||||
}
|
||||
|
||||
/// Creates a character string from octets without length check.
|
||||
@@ -84,14 +81,58 @@ impl<Octs: ?Sized> CharStr<Octs> {
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that `octets` is at most 255 octets
|
||||
/// long. Otherwise, the behaviour is undefined.
|
||||
/// long. Otherwise, the behavior is undefined.
|
||||
pub unsafe fn from_octets_unchecked(octets: Octs) -> Self
|
||||
where
|
||||
Octs: Sized,
|
||||
{
|
||||
CharStr(octets)
|
||||
}
|
||||
}
|
||||
|
||||
impl CharStr<[u8]> {
|
||||
/// Creates a character string from an octets slice.
|
||||
pub fn from_slice(slice: &[u8]) -> Result<&Self, CharStrError> {
|
||||
Self::check_slice(slice)?;
|
||||
Ok(unsafe { Self::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Creates a new empty character string on an octets slice.
|
||||
pub fn empty_slice() -> &'static Self {
|
||||
unsafe { Self::from_slice_unchecked(b"".as_ref()) }
|
||||
}
|
||||
|
||||
/// Creates a character string from an octets slice without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that `octets` is at most 255 octets
|
||||
/// long. Otherwise, the behaviour is undefined.
|
||||
pub unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
|
||||
&*(slice as *const [u8] as *const Self)
|
||||
}
|
||||
|
||||
/// Creates a character string from a mutable slice without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller has to make sure that `octets` is at most 255 octets
|
||||
/// long. Otherwise, the behaviour is undefined.
|
||||
unsafe fn from_slice_mut_unchecked(slice: &mut [u8]) -> &mut Self {
|
||||
&mut *(slice as *mut [u8] as *mut Self)
|
||||
}
|
||||
|
||||
/// Checks whether an octets slice contains a correct character string.
|
||||
fn check_slice(slice: &[u8]) -> Result<(), CharStrError> {
|
||||
if slice.len() > 255 {
|
||||
Err(CharStrError)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: ?Sized> CharStr<Octs> {
|
||||
/// Creates a new empty builder for this character string type.
|
||||
pub fn builder() -> CharStrBuilder<Octs::Builder>
|
||||
where
|
||||
@@ -123,19 +164,19 @@ impl<Octs: ?Sized> CharStr<Octs> {
|
||||
}
|
||||
|
||||
/// Returns a character string atop a slice of the content.
|
||||
pub fn for_slice(&self) -> CharStr<&[u8]>
|
||||
pub fn for_slice(&self) -> &CharStr<[u8]>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
unsafe { CharStr::from_octets_unchecked(self.0.as_ref()) }
|
||||
unsafe { CharStr::from_slice_unchecked(self.0.as_ref()) }
|
||||
}
|
||||
|
||||
/// Returns a character string atop a mutable slice of the content.
|
||||
pub fn for_slice_mut(&mut self) -> CharStr<&mut [u8]>
|
||||
pub fn for_slice_mut(&mut self) -> &mut CharStr<[u8]>
|
||||
where
|
||||
Octs: AsMut<[u8]>,
|
||||
{
|
||||
unsafe { CharStr::from_octets_unchecked(self.0.as_mut()) }
|
||||
unsafe { CharStr::from_slice_mut_unchecked(self.0.as_mut()) }
|
||||
}
|
||||
|
||||
/// Returns a reference to a slice of the character string’s data.
|
||||
@@ -206,36 +247,6 @@ impl<Octets> CharStr<Octets> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bytes")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))]
|
||||
impl CharStr<Bytes> {
|
||||
/// Creates a new character string from a bytes value.
|
||||
///
|
||||
/// Returns succesfully if the bytes slice can indeed be used as a
|
||||
/// character string, i.e., it is not longer than 255 bytes.
|
||||
pub fn from_bytes(bytes: Bytes) -> Result<Self, CharStrError> {
|
||||
if bytes.len() > 255 {
|
||||
Err(CharStrError)
|
||||
} else {
|
||||
Ok(unsafe { Self::from_octets_unchecked(bytes) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CharStr<[u8]> {
|
||||
/// Creates a new character string from an octet slice.
|
||||
///
|
||||
/// If the byte slice is longer than 255 bytes, the function will return
|
||||
/// an error.
|
||||
pub fn from_slice(slice: &[u8]) -> Result<&Self, CharStrError> {
|
||||
if slice.len() > 255 {
|
||||
Err(CharStrError)
|
||||
} else {
|
||||
Ok(unsafe { &*(slice as *const [u8] as *const CharStr<[u8]>) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- OctetsFrom
|
||||
|
||||
impl<Octs, SrcOcts> OctetsFrom<CharStr<SrcOcts>> for CharStr<Octs>
|
||||
@@ -282,6 +293,8 @@ where
|
||||
}
|
||||
|
||||
//--- Deref and AsRef
|
||||
//
|
||||
// No Borrow as character strings compare ignoring case.
|
||||
|
||||
impl<Octets: ?Sized> ops::Deref for CharStr<Octets> {
|
||||
type Target = Octets;
|
||||
@@ -375,7 +388,7 @@ impl<T: AsRef<[u8]> + ?Sized> hash::Hash for CharStr<T> {
|
||||
}
|
||||
}
|
||||
|
||||
//--- Display
|
||||
//--- Display and Debug
|
||||
|
||||
impl<T: AsRef<[u8]> + ?Sized> fmt::Display for CharStr<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
@@ -404,6 +417,14 @@ impl<T: AsRef<[u8]> + ?Sized> fmt::UpperHex for CharStr<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]> + ?Sized> fmt::Debug for CharStr<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("CharStr")
|
||||
.field(&format_args!("{}", self))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
//--- IntoIterator
|
||||
|
||||
impl<T: AsRef<[u8]>> IntoIterator for CharStr<T> {
|
||||
@@ -424,20 +445,13 @@ impl<'a, T: AsRef<[u8]> + ?Sized + 'a> IntoIterator for &'a CharStr<T> {
|
||||
}
|
||||
}
|
||||
|
||||
//--- Debug
|
||||
|
||||
impl<T: AsRef<[u8]> + ?Sized> fmt::Debug for CharStr<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("CharStr")
|
||||
.field(&format_args!("{}", self))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
//--- Serialize and Deserialize
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T: AsRef<[u8]> + SerializeOctets> serde::Serialize for CharStr<T> {
|
||||
impl<T> serde::Serialize for CharStr<T>
|
||||
where
|
||||
T: AsRef<[u8]> + SerializeOctets + ?Sized,
|
||||
{
|
||||
fn serialize<S: serde::Serializer>(
|
||||
&self,
|
||||
serializer: S,
|
||||
@@ -775,7 +789,7 @@ pub struct CharStrError;
|
||||
|
||||
impl fmt::Display for CharStrError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str("illegal character string")
|
||||
f.write_str("long character string")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -863,22 +877,14 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "bytes")]
|
||||
fn from_bytes() {
|
||||
fn from_octets() {
|
||||
assert_eq!(
|
||||
CharStr::from_bytes(bytes::Bytes::from_static(b"01234"))
|
||||
.unwrap()
|
||||
.as_slice(),
|
||||
CharStr::from_octets("01234").unwrap().as_slice(),
|
||||
b"01234"
|
||||
);
|
||||
assert_eq!(
|
||||
CharStr::from_bytes(bytes::Bytes::from_static(b""))
|
||||
.unwrap()
|
||||
.as_slice(),
|
||||
b""
|
||||
);
|
||||
assert!(CharStr::from_bytes(vec![0; 255].into()).is_ok());
|
||||
assert!(CharStr::from_bytes(vec![0; 256].into()).is_err());
|
||||
assert_eq!(CharStr::from_octets("").unwrap().as_slice(), b"");
|
||||
assert!(CharStr::from_octets(vec![0; 255]).is_ok());
|
||||
assert!(CharStr::from_octets(vec![0; 256]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+66
-18
@@ -22,7 +22,7 @@ use super::wire::{Composer, ParseError};
|
||||
use crate::rdata::rfc1035::Cname;
|
||||
use core::marker::PhantomData;
|
||||
use core::{fmt, mem};
|
||||
use octseq::{Octets, OctetsFrom, Parser, ShortBuf};
|
||||
use octseq::{Octets, OctetsFrom, Parser};
|
||||
|
||||
//------------ Message -------------------------------------------------------
|
||||
|
||||
@@ -156,35 +156,67 @@ pub struct Message<Octs: ?Sized> {
|
||||
|
||||
/// # Creation and Conversion
|
||||
///
|
||||
impl<Octs: ?Sized> Message<Octs> {
|
||||
impl<Octs> Message<Octs> {
|
||||
/// Creates a message from an octets sequence.
|
||||
///
|
||||
/// This fails if the slice is too short to even contain a complete
|
||||
/// header section. No further checks are done, though, so if this
|
||||
/// function returns ok, the message may still be broken with other
|
||||
/// methods returning errors later one.
|
||||
pub fn from_octets(octets: Octs) -> Result<Self, ShortBuf>
|
||||
pub fn from_octets(octets: Octs) -> Result<Self, ShortMessage>
|
||||
where
|
||||
Octs: AsRef<[u8]> + Sized,
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
if octets.as_ref().len() < mem::size_of::<HeaderSection>() {
|
||||
Err(ShortBuf)
|
||||
} else {
|
||||
Ok(unsafe { Self::from_octets_unchecked(octets) })
|
||||
}
|
||||
Message::check_slice(octets.as_ref())?;
|
||||
Ok(unsafe { Self::from_octets_unchecked(octets) })
|
||||
}
|
||||
|
||||
/// Creates a message from a bytes value without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The methods for header access rely on the octets being at least as
|
||||
/// long as a header, so this is unsafe.
|
||||
pub(super) unsafe fn from_octets_unchecked(octets: Octs) -> Self
|
||||
where
|
||||
Octs: Sized,
|
||||
{
|
||||
/// long as a header. If the sequence is shorter, the behavior is
|
||||
/// undefined.
|
||||
pub(super) unsafe fn from_octets_unchecked(octets: Octs) -> Self {
|
||||
Message { octets }
|
||||
}
|
||||
}
|
||||
|
||||
impl Message<[u8]> {
|
||||
/// Creates a message from an octets slice.
|
||||
///
|
||||
/// This fails if the slice is too short to even contain a complete
|
||||
/// header section. No further checks are done, though, so if this
|
||||
/// function returns ok, the message may still be broken with other
|
||||
/// methods returning errors later one.
|
||||
pub fn from_slice(slice: &[u8]) -> Result<&Self, ShortMessage> {
|
||||
Message::check_slice(slice)?;
|
||||
Ok(unsafe { Self::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Creates a message from a bytes value without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The methods for header access rely on the octets being at least as
|
||||
/// long as a header. If the sequence is shorter, the behavior is
|
||||
/// undefined.
|
||||
unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
|
||||
&*(slice as *const [u8] as *const Self)
|
||||
}
|
||||
|
||||
/// Checks that the slice can be used for a message.
|
||||
fn check_slice(slice: &[u8]) -> Result<(), ShortMessage> {
|
||||
if slice.len() < mem::size_of::<HeaderSection>() {
|
||||
Err(ShortMessage(()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: ?Sized> Message<Octs> {
|
||||
/// Returns a reference to the underlying octets sequence.
|
||||
pub fn as_octets(&self) -> &Octs {
|
||||
&self.octets
|
||||
@@ -222,9 +254,7 @@ impl<Octs: ?Sized> Message<Octs> {
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
unsafe {
|
||||
&*(self.octets.as_ref() as *const [u8] as *const Message<[u8]>)
|
||||
}
|
||||
unsafe { Message::from_slice_unchecked(self.octets.as_ref()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,6 +626,9 @@ impl<Octs: Octets + ?Sized> Message<Octs> {
|
||||
|
||||
//--- AsRef
|
||||
|
||||
// Octs here can’t be ?Sized or it’ll conflict with AsRef<[u8]> below.
|
||||
// But [u8] is covered by that impl anyway, so no harm done.
|
||||
//
|
||||
impl<Octs> AsRef<Octs> for Message<Octs> {
|
||||
fn as_ref(&self) -> &Octs {
|
||||
&self.octets
|
||||
@@ -931,7 +964,7 @@ impl<'a, Octs: Octets + ?Sized> RecordSection<'a, Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
//--- Clone
|
||||
//--- Clone and Copy
|
||||
|
||||
impl<'a, Octs: ?Sized> Clone for RecordSection<'a, Octs> {
|
||||
fn clone(&self) -> Self {
|
||||
@@ -1103,6 +1136,21 @@ where
|
||||
|
||||
//============ Error Types ===================================================
|
||||
|
||||
//------------ ShortMessage --------------------------------------------------
|
||||
|
||||
/// A message was too short to even contain the header.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ShortMessage(());
|
||||
|
||||
impl fmt::Display for ShortMessage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str("short message")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for ShortMessage {}
|
||||
|
||||
//------------ CopyRecordsError ----------------------------------------------
|
||||
|
||||
/// An error occurrd while copying records.
|
||||
|
||||
@@ -234,7 +234,7 @@ impl<Target: Composer> MessageBuilder<Target> {
|
||||
///
|
||||
/// The method converts the message builder into an answer builder ready
|
||||
/// to receive the answer for the question.
|
||||
pub fn start_answer<Octs: Octets>(
|
||||
pub fn start_answer<Octs: Octets + ?Sized>(
|
||||
mut self,
|
||||
msg: &Message<Octs>,
|
||||
rcode: Rcode,
|
||||
@@ -1505,12 +1505,12 @@ where
|
||||
/// header values of the record and push options to the record data.
|
||||
///
|
||||
/// [`AdditionalBuilder::opt`]: struct.AdditonalBuilder.html#method.opt
|
||||
pub struct OptBuilder<'a, Target: AsRef<[u8]> + AsMut<[u8]>> {
|
||||
pub struct OptBuilder<'a, Target: ?Sized> {
|
||||
start: usize,
|
||||
target: &'a mut Target,
|
||||
}
|
||||
|
||||
impl<'a, Target: Composer> OptBuilder<'a, Target> {
|
||||
impl<'a, Target: Composer + ?Sized> OptBuilder<'a, Target> {
|
||||
/// Creates a new opt builder atop an additional builder.
|
||||
fn new(target: &'a mut Target) -> Result<Self, ShortBuf> {
|
||||
let start = target.as_ref().len();
|
||||
@@ -1544,7 +1544,7 @@ impl<'a, Target: Composer> OptBuilder<'a, Target> {
|
||||
}
|
||||
|
||||
/// Appends an option to the OPT record.
|
||||
pub fn push<Opt: ComposeOptData>(
|
||||
pub fn push<Opt: ComposeOptData + ?Sized>(
|
||||
&mut self,
|
||||
opt: &Opt,
|
||||
) -> Result<(), Target::AppendError> {
|
||||
|
||||
+18
-14
@@ -13,7 +13,7 @@ use super::traits::{ToDname, ToLabelIter};
|
||||
use bytes::Bytes;
|
||||
use core::ops::{Bound, RangeBounds};
|
||||
use core::str::FromStr;
|
||||
use core::{cmp, fmt, hash, ops, str};
|
||||
use core::{cmp, fmt, hash, str};
|
||||
use octseq::builder::{EmptyBuilder, FreezeBuilder, FromBuilder, Truncate};
|
||||
use octseq::octets::{Octets, OctetsFrom};
|
||||
use octseq::parse::Parser;
|
||||
@@ -258,11 +258,11 @@ impl<Octs: ?Sized> Dname<Octs> {
|
||||
}
|
||||
|
||||
/// Returns a domain name for the octets slice of the content.
|
||||
pub fn for_slice(&self) -> Dname<&[u8]>
|
||||
pub fn for_slice(&self) -> &Dname<[u8]>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
unsafe { Dname::from_octets_unchecked(self.0.as_ref()) }
|
||||
unsafe { Dname::from_slice_unchecked(self.0.as_ref()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,6 +275,12 @@ impl<Octs: AsRef<[u8]> + ?Sized> Dname<Octs> {
|
||||
pub fn is_root(&self) -> bool {
|
||||
self.0.as_ref().len() == 1
|
||||
}
|
||||
|
||||
/// Returns the length of the domain name.
|
||||
#[allow(clippy::len_without_is_empty)] // never empty ...
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.as_ref().len()
|
||||
}
|
||||
}
|
||||
|
||||
/// # Working with Labels
|
||||
@@ -495,7 +501,7 @@ impl<Octs: AsRef<[u8]> + ?Sized> Dname<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Dname<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Dname<Octs> {
|
||||
/// Splits the name into two at the given position.
|
||||
///
|
||||
/// Returns a pair of the left and right part of the split name.
|
||||
@@ -531,7 +537,7 @@ impl<Octs: AsRef<[u8]>> Dname<Octs> {
|
||||
/// it is out of bounds.
|
||||
pub fn truncate(mut self, len: usize) -> RelativeDname<Octs>
|
||||
where
|
||||
Octs: Truncate,
|
||||
Octs: Truncate + Sized,
|
||||
{
|
||||
self.check_index(len);
|
||||
self.0.truncate(len);
|
||||
@@ -574,7 +580,7 @@ impl<Octs: AsRef<[u8]>> Dname<Octs> {
|
||||
base: &N,
|
||||
) -> Result<RelativeDname<Octs>, Self>
|
||||
where
|
||||
Octs: Truncate,
|
||||
Octs: Truncate + Sized,
|
||||
{
|
||||
if self.ends_with(base) {
|
||||
let len = self.0.as_ref().len() - usize::from(base.compose_len());
|
||||
@@ -620,18 +626,16 @@ impl<Octs> Dname<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
//--- Deref and AsRef
|
||||
//--- AsRef
|
||||
|
||||
impl<Octs: ?Sized> ops::Deref for Dname<Octs> {
|
||||
type Target = Octs;
|
||||
|
||||
fn deref(&self) -> &Octs {
|
||||
impl<Octs> AsRef<Octs> for Dname<Octs> {
|
||||
fn as_ref(&self) -> &Octs {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<T> + ?Sized, T: ?Sized> AsRef<T> for Dname<Octs> {
|
||||
fn as_ref(&self) -> &T {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for Dname<Octs> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
@@ -807,7 +811,7 @@ impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Dname<Octs> {
|
||||
#[cfg(feature = "serde")]
|
||||
impl<Octs> serde::Serialize for Dname<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]> + SerializeOctets,
|
||||
Octs: AsRef<[u8]> + SerializeOctets + ?Sized,
|
||||
{
|
||||
fn serialize<S: serde::Serializer>(
|
||||
&self,
|
||||
|
||||
+24
-12
@@ -12,7 +12,7 @@ use super::traits::{ToLabelIter, ToRelativeDname};
|
||||
use bytes::Bytes;
|
||||
use core::cmp::Ordering;
|
||||
use core::ops::{Bound, RangeBounds};
|
||||
use core::{cmp, fmt, hash, ops};
|
||||
use core::{cmp, fmt, hash};
|
||||
#[cfg(feature = "serde")]
|
||||
use octseq::builder::{EmptyBuilder, FromBuilder};
|
||||
use octseq::builder::{FreezeBuilder, IntoBuilder, Truncate};
|
||||
@@ -206,11 +206,11 @@ impl<Octs: ?Sized> RelativeDname<Octs> {
|
||||
}
|
||||
|
||||
/// Returns a domain name for the octets slice of the content.
|
||||
pub fn for_slice(&self) -> RelativeDname<&[u8]>
|
||||
pub fn for_slice(&self) -> &RelativeDname<[u8]>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
unsafe { RelativeDname::from_octets_unchecked(self.0.as_ref()) }
|
||||
unsafe { RelativeDname::from_slice_unchecked(self.0.as_ref()) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +270,20 @@ impl<Octs> RelativeDname<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
/// # Properties
|
||||
///
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
|
||||
/// Returns the length of the name.
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.as_ref().len()
|
||||
}
|
||||
|
||||
/// Returns whether the name is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.as_ref().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// # Working with Labels
|
||||
///
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
|
||||
@@ -406,7 +420,7 @@ impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> RelativeDname<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> RelativeDname<Octs> {
|
||||
/// Splits the name into two at the given position.
|
||||
///
|
||||
/// Returns a pair of the left and right part of the split name.
|
||||
@@ -500,18 +514,16 @@ impl<Octs: AsRef<[u8]>> RelativeDname<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
//--- Deref and AsRef
|
||||
//--- AsRef
|
||||
|
||||
impl<Octs: ?Sized> ops::Deref for RelativeDname<Octs> {
|
||||
type Target = Octs;
|
||||
|
||||
fn deref(&self) -> &Octs {
|
||||
impl<Octs> AsRef<Octs> for RelativeDname<Octs> {
|
||||
fn as_ref(&self) -> &Octs {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<T> + ?Sized, T: ?Sized> AsRef<T> for RelativeDname<Octs> {
|
||||
fn as_ref(&self) -> &T {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for RelativeDname<Octs> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
@@ -643,7 +655,7 @@ impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for RelativeDname<Octs> {
|
||||
#[cfg(feature = "serde")]
|
||||
impl<Octs> serde::Serialize for RelativeDname<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]> + SerializeOctets,
|
||||
Octs: AsRef<[u8]> + SerializeOctets + ?Sized,
|
||||
{
|
||||
fn serialize<S: serde::Serializer>(
|
||||
&self,
|
||||
|
||||
@@ -320,8 +320,17 @@ where
|
||||
|
||||
//--- AsRef
|
||||
|
||||
impl<Octets: AsRef<T>, T> AsRef<T> for UncertainDname<Octets> {
|
||||
fn as_ref(&self) -> &T {
|
||||
impl<Octs> AsRef<Octs> for UncertainDname<Octs> {
|
||||
fn as_ref(&self) -> &Octs {
|
||||
match *self {
|
||||
UncertainDname::Absolute(ref name) => name.as_ref(),
|
||||
UncertainDname::Relative(ref name) => name.as_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> AsRef<[u8]> for UncertainDname<Octs> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
match *self {
|
||||
UncertainDname::Absolute(ref name) => name.as_ref(),
|
||||
UncertainDname::Relative(ref name) => name.as_ref(),
|
||||
|
||||
+62
-24
@@ -71,7 +71,7 @@ use octseq::parse::Parser;
|
||||
/// [`iter`]: #method.iter
|
||||
/// [`OptRecord`]: struct.OptRecord.html
|
||||
#[derive(Clone)]
|
||||
pub struct Opt<Octs> {
|
||||
pub struct Opt<Octs: ?Sized> {
|
||||
octets: Octs,
|
||||
}
|
||||
|
||||
@@ -81,13 +81,54 @@ impl<Octs: AsRef<[u8]>> Opt<Octs> {
|
||||
/// The function checks whether the octets contain a sequence of
|
||||
/// options. It does not check whether the options themselves are valid.
|
||||
pub fn from_octets(octets: Octs) -> Result<Self, ParseError> {
|
||||
let mut parser = Parser::from_ref(octets.as_ref());
|
||||
Opt::check_slice(octets.as_ref())?;
|
||||
Ok(Opt { octets })
|
||||
}
|
||||
|
||||
/// Parses OPT record data from the beginning of a parser.
|
||||
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
|
||||
parser: &mut Parser<'a, Src>,
|
||||
) -> Result<Self, ParseError> {
|
||||
let len = parser.remaining();
|
||||
Self::from_octets(parser.parse_octets(len)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Opt<[u8]> {
|
||||
/// Creates OPT record data from an octets slice.
|
||||
pub fn from_slice(slice: &[u8]) -> Result<&Self, ParseError> {
|
||||
Self::check_slice(slice)?;
|
||||
Ok(unsafe { Self::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Creates OPT record data from an octets slice without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller needs to ensure that the slice contains correctly encoded
|
||||
/// OPT record data. The data of the options themselves does not need to
|
||||
/// be correct.
|
||||
unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
|
||||
&*(slice as *const [u8] as *const Self)
|
||||
}
|
||||
|
||||
/// Checks that the slice contains acceptable OPT record data.
|
||||
fn check_slice(slice: &[u8]) -> Result<(), ParseError> {
|
||||
let mut parser = Parser::from_ref(slice);
|
||||
while parser.remaining() > 0 {
|
||||
parser.advance(2)?;
|
||||
let len = parser.parse_u16()?;
|
||||
parser.advance(len as usize)?;
|
||||
}
|
||||
Ok(Opt { octets })
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Opt<Octs> {
|
||||
/// Returns the length of the OPT record data.
|
||||
#[allow(clippy::len_without_is_empty)] // never empty.
|
||||
pub fn len(&self) -> usize {
|
||||
self.octets.as_ref().len()
|
||||
}
|
||||
|
||||
/// Returns an iterator over options of a given type.
|
||||
@@ -101,13 +142,6 @@ impl<Octs: AsRef<[u8]>> Opt<Octs> {
|
||||
{
|
||||
OptIter::new(&self.octets)
|
||||
}
|
||||
|
||||
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
|
||||
parser: &mut Parser<'a, Src>,
|
||||
) -> Result<Self, ParseError> {
|
||||
let len = parser.remaining();
|
||||
Self::from_octets(parser.parse_octets(len)?)
|
||||
}
|
||||
}
|
||||
|
||||
//--- OctetsFrom
|
||||
@@ -127,29 +161,29 @@ where
|
||||
|
||||
impl<Octs, Other> PartialEq<Opt<Other>> for Opt<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
Other: AsRef<[u8]>,
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn eq(&self, other: &Opt<Other>) -> bool {
|
||||
self.octets.as_ref().eq(other.octets.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Eq for Opt<Octs> {}
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Eq for Opt<Octs> {}
|
||||
|
||||
//--- PartialOrd and Ord
|
||||
|
||||
impl<Octs, Other> PartialOrd<Opt<Other>> for Opt<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
Other: AsRef<[u8]>,
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Opt<Other>) -> Option<Ordering> {
|
||||
self.octets.as_ref().partial_cmp(other.octets.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Ord for Opt<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Ord for Opt<Octs> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.octets.as_ref().cmp(other.octets.as_ref())
|
||||
}
|
||||
@@ -157,7 +191,7 @@ impl<Octs: AsRef<[u8]>> Ord for Opt<Octs> {
|
||||
|
||||
//--- Hash
|
||||
|
||||
impl<Octs: AsRef<[u8]>> hash::Hash for Opt<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for Opt<Octs> {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
self.octets.as_ref().hash(state)
|
||||
}
|
||||
@@ -165,7 +199,7 @@ impl<Octs: AsRef<[u8]>> hash::Hash for Opt<Octs> {
|
||||
|
||||
//--- RecordData, ParseRecordData, and ComposeRecordData
|
||||
|
||||
impl<Octs> RecordData for Opt<Octs> {
|
||||
impl<Octs: ?Sized> RecordData for Opt<Octs> {
|
||||
fn rtype(&self) -> Rtype {
|
||||
Rtype::Opt
|
||||
}
|
||||
@@ -187,7 +221,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> ComposeRecordData for Opt<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> ComposeRecordData for Opt<Octs> {
|
||||
fn rdlen(&self, _compress: bool) -> Option<u16> {
|
||||
Some(u16::try_from(self.octets.as_ref().len()).expect("long OPT"))
|
||||
}
|
||||
@@ -209,14 +243,14 @@ impl<Octs: AsRef<[u8]>> ComposeRecordData for Opt<Octs> {
|
||||
|
||||
//--- Display
|
||||
|
||||
impl<Octs: AsRef<[u8]>> fmt::Display for Opt<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for Opt<Octs> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// XXX TODO Print this properly.
|
||||
f.write_str("OPT ...")
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> fmt::Debug for Opt<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Opt<Octs> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str("Opt(")?;
|
||||
fmt::Display::fmt(self, f)?;
|
||||
@@ -527,7 +561,7 @@ impl OptionHeader {
|
||||
/// particular option. After such an error you can continue to iterate until
|
||||
/// `None` indicates that you’ve reached the end of the record.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OptIter<'a, Octs: Octets, D: ParseOptData<'a, Octs>> {
|
||||
pub struct OptIter<'a, Octs: ?Sized, D> {
|
||||
/// A parser for the OPT record data.
|
||||
parser: Parser<'a, Octs>,
|
||||
|
||||
@@ -535,7 +569,11 @@ pub struct OptIter<'a, Octs: Octets, D: ParseOptData<'a, Octs>> {
|
||||
marker: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<'a, Octs: Octets, D: ParseOptData<'a, Octs>> OptIter<'a, Octs, D> {
|
||||
impl<'a, Octs, D> OptIter<'a, Octs, D>
|
||||
where
|
||||
Octs: Octets + ?Sized,
|
||||
D: ParseOptData<'a, Octs>,
|
||||
{
|
||||
/// Creates an iterator from a reference to the OPT record data.
|
||||
fn new(octets: &'a Octs) -> Self {
|
||||
OptIter {
|
||||
@@ -565,7 +603,7 @@ impl<'a, Octs: Octets, D: ParseOptData<'a, Octs>> OptIter<'a, Octs, D> {
|
||||
|
||||
impl<'a, Octs, Data> Iterator for OptIter<'a, Octs, Data>
|
||||
where
|
||||
Octs: Octets,
|
||||
Octs: Octets + ?Sized,
|
||||
Data: ParseOptData<'a, Octs>,
|
||||
{
|
||||
type Item = Result<Data, ParseError>;
|
||||
|
||||
+62
-18
@@ -17,7 +17,7 @@ use core::cmp::Ordering;
|
||||
///
|
||||
/// Specified in RFC 5001.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Nsid<Octs> {
|
||||
pub struct Nsid<Octs: ?Sized> {
|
||||
octets: Octs,
|
||||
}
|
||||
|
||||
@@ -32,47 +32,83 @@ impl<Octs> Nsid<Octs> {
|
||||
let len = parser.remaining();
|
||||
parser.parse_octets(len).map(Nsid::from_octets).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl Nsid<[u8]> {
|
||||
pub fn from_slice(slice: &[u8]) -> &Self {
|
||||
unsafe { &*(slice as *const [u8] as *const Self) }
|
||||
}
|
||||
|
||||
pub fn from_slice_mut(slice: &mut [u8]) -> &mut Self {
|
||||
unsafe { &mut *(slice as *mut [u8] as *mut Self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: ?Sized> Nsid<Octs> {
|
||||
pub fn as_octets(&self) -> &Octs {
|
||||
&self.octets
|
||||
}
|
||||
|
||||
pub fn into_octets(self) -> Octs {
|
||||
pub fn into_octets(self) -> Octs
|
||||
where
|
||||
Octs: Sized,
|
||||
{
|
||||
self.octets
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8]
|
||||
where Octs: AsRef<[u8]> {
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
self.octets.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_slice_mut(&mut self) -> &mut [u8]
|
||||
where Octs: AsMut<[u8]> {
|
||||
where
|
||||
Octs: AsMut<[u8]>,
|
||||
{
|
||||
self.octets.as_mut()
|
||||
}
|
||||
|
||||
pub fn for_slice(&self) -> &Nsid<[u8]>
|
||||
where
|
||||
Octs: AsRef<[u8]>
|
||||
{
|
||||
Nsid::from_slice(self.octets.as_ref())
|
||||
}
|
||||
|
||||
pub fn for_slice_mut(&mut self) -> &mut Nsid<[u8]>
|
||||
where
|
||||
Octs: AsMut<[u8]>
|
||||
{
|
||||
Nsid::from_slice_mut(self.octets.as_mut())
|
||||
}
|
||||
}
|
||||
|
||||
//--- AsRef, AsMut, Borrow, BorrowMut
|
||||
|
||||
impl<Octs: AsRef<[u8]>> AsRef<[u8]> for Nsid<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for Nsid<Octs> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsMut<[u8]>> AsMut<[u8]> for Nsid<Octs> {
|
||||
impl<Octs: AsMut<[u8]> + ?Sized> AsMut<[u8]> for Nsid<Octs> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> borrow::Borrow<[u8]> for Nsid<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> borrow::Borrow<[u8]> for Nsid<Octs> {
|
||||
fn borrow(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsMut<[u8]> + AsRef<[u8]>> borrow::BorrowMut<[u8]> for Nsid<Octs> {
|
||||
impl<Octs> borrow::BorrowMut<[u8]> for Nsid<Octs>
|
||||
where
|
||||
Octs: AsMut<[u8]> + AsRef<[u8]> + ?Sized
|
||||
{
|
||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
}
|
||||
@@ -80,7 +116,7 @@ impl<Octs: AsMut<[u8]> + AsRef<[u8]>> borrow::BorrowMut<[u8]> for Nsid<Octs> {
|
||||
|
||||
//--- OptData etc.
|
||||
|
||||
impl<Octs> OptData for Nsid<Octs> {
|
||||
impl<Octs: ?Sized> OptData for Nsid<Octs> {
|
||||
fn code(&self) -> OptionCode {
|
||||
OptionCode::Nsid
|
||||
}
|
||||
@@ -100,7 +136,7 @@ impl<'a, Octs: Octets> ParseOptData<'a, Octs> for Nsid<Octs::Range<'a>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> ComposeOptData for Nsid<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> ComposeOptData for Nsid<Octs> {
|
||||
fn compose_len(&self) -> u16 {
|
||||
self.octets.as_ref().len().try_into().expect("long option data")
|
||||
}
|
||||
@@ -114,7 +150,7 @@ impl<Octs: AsRef<[u8]>> ComposeOptData for Nsid<Octs> {
|
||||
|
||||
//--- Display
|
||||
|
||||
impl<Octs: AsRef<[u8]>> fmt::Display for Nsid<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> fmt::Display for Nsid<Octs> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// RFC 5001 § 2.4:
|
||||
// | User interfaces MUST read and write the contents of the NSID
|
||||
@@ -132,23 +168,31 @@ impl<Octs: AsRef<[u8]>> fmt::Display for Nsid<Octs> {
|
||||
|
||||
//--- PartialEq and Eq
|
||||
|
||||
impl<Octs: AsRef<[u8]>, Other: AsRef<[u8]>> PartialEq<Other> for Nsid<Octs> {
|
||||
impl<Octs, Other> PartialEq<Other> for Nsid<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn eq(&self, other: &Other) -> bool {
|
||||
self.as_slice().eq(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Eq for Nsid<Octs> { }
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Eq for Nsid<Octs> { }
|
||||
|
||||
//--- PartialOrd and Ord
|
||||
|
||||
impl<Octs: AsRef<[u8]>, Other: AsRef<[u8]>> PartialOrd<Other> for Nsid<Octs> {
|
||||
impl<Octs, Other> PartialOrd<Other> for Nsid<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Other) -> Option<Ordering> {
|
||||
self.as_slice().partial_cmp(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Ord for Nsid<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Ord for Nsid<Octs> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.as_slice().cmp(other.as_slice())
|
||||
}
|
||||
@@ -156,7 +200,7 @@ impl<Octs: AsRef<[u8]>> Ord for Nsid<Octs> {
|
||||
|
||||
//--- Hash
|
||||
|
||||
impl<Octs: AsRef<[u8]>> hash::Hash for Nsid<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for Nsid<Octs> {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_slice().hash(state)
|
||||
}
|
||||
@@ -167,9 +211,9 @@ impl<Octs: AsRef<[u8]>> hash::Hash for Nsid<Octs> {
|
||||
|
||||
impl<'a, Target: Composer> OptBuilder<'a, Target> {
|
||||
pub fn nsid(
|
||||
&mut self, data: &impl AsRef<[u8]>
|
||||
&mut self, data: &(impl AsRef<[u8]> + ?Sized)
|
||||
) -> Result<(), Target::AppendError> {
|
||||
self.push(&Nsid::from_octets(data.as_ref()))
|
||||
self.push(Nsid::from_slice(data.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+75
-40
@@ -16,7 +16,7 @@ use core::cmp::Ordering;
|
||||
macro_rules! option_type {
|
||||
( $name:ident, $fn:ident ) => {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct $name<Octs> {
|
||||
pub struct $name<Octs: ?Sized> {
|
||||
octets: Octs,
|
||||
}
|
||||
|
||||
@@ -25,29 +25,6 @@ macro_rules! option_type {
|
||||
$name { octets }
|
||||
}
|
||||
|
||||
pub fn as_octets(&self) -> &Octs {
|
||||
&self.octets
|
||||
}
|
||||
|
||||
pub fn into_octets(self) -> Octs {
|
||||
self.octets
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8]
|
||||
where Octs: AsRef<[u8]> {
|
||||
self.octets.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_slice_mut(&mut self) -> &mut [u8]
|
||||
where Octs: AsMut<[u8]> {
|
||||
self.octets.as_mut()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> SecAlgsIter
|
||||
where Octs: AsRef<[u8]> {
|
||||
SecAlgsIter::new(self.octets.as_ref())
|
||||
}
|
||||
|
||||
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
|
||||
parser: &mut Parser<'a, Src>
|
||||
) -> Result<Self, ParseError> {
|
||||
@@ -58,21 +35,79 @@ macro_rules! option_type {
|
||||
}
|
||||
}
|
||||
|
||||
impl $name<[u8]> {
|
||||
pub fn from_slice(slice: &[u8]) -> &Self {
|
||||
unsafe { &*(slice as *const [u8] as *const Self) }
|
||||
}
|
||||
|
||||
pub fn from_slice_mut(slice: &mut [u8]) -> &mut Self {
|
||||
unsafe { &mut *(slice as *mut [u8] as *mut Self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: ?Sized> $name<Octs> {
|
||||
pub fn as_octets(&self) -> &Octs {
|
||||
&self.octets
|
||||
}
|
||||
|
||||
pub fn into_octets(self) -> Octs
|
||||
where
|
||||
Octs: Sized,
|
||||
{
|
||||
self.octets
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8]
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
self.octets.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_slice_mut(&mut self) -> &mut [u8]
|
||||
where
|
||||
Octs: AsMut<[u8]>,
|
||||
{
|
||||
self.octets.as_mut()
|
||||
}
|
||||
|
||||
pub fn for_slice(&self) -> &$name<[u8]>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
$name::from_slice(self.octets.as_ref())
|
||||
}
|
||||
|
||||
pub fn for_slice_mut(&mut self) -> &mut $name<[u8]>
|
||||
where
|
||||
Octs: AsMut<[u8]>,
|
||||
{
|
||||
$name::from_slice_mut(self.octets.as_mut())
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> SecAlgsIter
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
SecAlgsIter::new(self.octets.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
//--- AsRef, AsMut, Borrow, BorrowMut
|
||||
|
||||
impl<Octs: AsRef<[u8]>> AsRef<[u8]> for $name<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for $name<Octs> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsMut<[u8]>> AsMut<[u8]> for $name<Octs> {
|
||||
impl<Octs: AsMut<[u8]> + ?Sized> AsMut<[u8]> for $name<Octs> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> borrow::Borrow<[u8]> for $name<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> borrow::Borrow<[u8]> for $name<Octs> {
|
||||
fn borrow(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
@@ -80,7 +115,7 @@ macro_rules! option_type {
|
||||
|
||||
impl<Octs> borrow::BorrowMut<[u8]> for $name<Octs>
|
||||
where
|
||||
Octs: AsMut<[u8]> + AsRef<[u8]>,
|
||||
Octs: AsMut<[u8]> + AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
@@ -89,7 +124,7 @@ macro_rules! option_type {
|
||||
|
||||
//--- OptData etc.
|
||||
|
||||
impl<Octs> OptData for $name<Octs> {
|
||||
impl<Octs: ?Sized> OptData for $name<Octs> {
|
||||
fn code(&self) -> OptionCode {
|
||||
OptionCode::$name
|
||||
}
|
||||
@@ -110,7 +145,7 @@ macro_rules! option_type {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> ComposeOptData for $name<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> ComposeOptData for $name<Octs> {
|
||||
fn compose_len(&self) -> u16 {
|
||||
self.octets.as_ref().len().try_into().expect("long option data")
|
||||
}
|
||||
@@ -125,7 +160,7 @@ macro_rules! option_type {
|
||||
|
||||
//--- IntoIter
|
||||
|
||||
impl<'a, Octs: AsRef<[u8]>> IntoIterator for &'a $name<Octs> {
|
||||
impl<'a, Octs: AsRef<[u8]> + ?Sized> IntoIterator for &'a $name<Octs> {
|
||||
type Item = SecAlg;
|
||||
type IntoIter = SecAlgsIter<'a>;
|
||||
|
||||
@@ -136,7 +171,7 @@ macro_rules! option_type {
|
||||
|
||||
//--- Display
|
||||
|
||||
impl<Octets: AsRef<[u8]>> fmt::Display for $name<Octets> {
|
||||
impl<Octets: AsRef<[u8]> + ?Sized> fmt::Display for $name<Octets> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut first = true;
|
||||
|
||||
@@ -156,29 +191,29 @@ macro_rules! option_type {
|
||||
|
||||
impl<Octs, Other> PartialEq<Other> for $name<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
Other: AsRef<[u8]>,
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn eq(&self, other: &Other) -> bool {
|
||||
self.as_slice().eq(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Eq for $name<Octs> { }
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Eq for $name<Octs> { }
|
||||
|
||||
//--- PartialOrd and Ord
|
||||
|
||||
impl<Octs, Other> PartialOrd<Other> for $name<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
Other: AsRef<[u8]>,
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Other) -> Option<Ordering> {
|
||||
self.as_slice().partial_cmp(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Ord for $name<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Ord for $name<Octs> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.as_slice().cmp(other.as_slice())
|
||||
}
|
||||
@@ -186,7 +221,7 @@ macro_rules! option_type {
|
||||
|
||||
//--- Hash
|
||||
|
||||
impl<Octs: AsRef<[u8]>> hash::Hash for $name<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for $name<Octs> {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_slice().hash(state)
|
||||
}
|
||||
@@ -196,7 +231,7 @@ macro_rules! option_type {
|
||||
|
||||
impl<'a, Target: Composer> OptBuilder<'a, Target> {
|
||||
pub fn $fn(
|
||||
&mut self, octets: &impl AsRef<[u8]>
|
||||
&mut self, octets: &(impl AsRef<[u8]> + ?Sized)
|
||||
) -> Result<(), Target::AppendError> {
|
||||
self.push(&$name::from_octets(octets.as_ref()))
|
||||
}
|
||||
|
||||
+71
-41
@@ -15,38 +15,15 @@ use core::convert::TryInto;
|
||||
//------------ KeyTag -------------------------------------------------------
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct KeyTag<Octs> {
|
||||
pub struct KeyTag<Octs: ?Sized> {
|
||||
octets: Octs,
|
||||
}
|
||||
|
||||
impl<Octs> KeyTag<Octs> {
|
||||
pub fn new(octets: Octs) -> Self {
|
||||
pub fn from_octets(octets: Octs) -> Self {
|
||||
KeyTag { octets }
|
||||
}
|
||||
|
||||
pub fn as_octets(&self) -> &Octs {
|
||||
&self.octets
|
||||
}
|
||||
|
||||
pub fn into_octets(self) -> Octs {
|
||||
self.octets
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8]
|
||||
where Octs: AsRef<[u8]> {
|
||||
self.octets.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_slice_mut(&mut self) -> &mut [u8]
|
||||
where Octs: AsMut<[u8]> {
|
||||
self.octets.as_mut()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> KeyTagIter
|
||||
where Octs: AsRef<[u8]> {
|
||||
KeyTagIter(self.octets.as_ref())
|
||||
}
|
||||
|
||||
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
|
||||
parser: &mut Parser<'a, Src>
|
||||
) -> Result<Self, ParseError> {
|
||||
@@ -55,32 +32,77 @@ impl<Octs> KeyTag<Octs> {
|
||||
Err(FormError::new("invalid keytag length").into())
|
||||
}
|
||||
else {
|
||||
Ok(Self::new(parser.parse_octets(len)?))
|
||||
Ok(Self::from_octets(parser.parse_octets(len)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyTag<[u8]> {
|
||||
pub fn from_slice(slice: &[u8]) -> &Self {
|
||||
unsafe { &*(slice as *const [u8] as *const Self) }
|
||||
}
|
||||
|
||||
pub fn from_slice_mut(slice: &mut [u8]) -> &mut Self {
|
||||
unsafe { &mut *(slice as *mut [u8] as *mut Self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: ?Sized> KeyTag<Octs> {
|
||||
pub fn as_octets(&self) -> &Octs {
|
||||
&self.octets
|
||||
}
|
||||
|
||||
pub fn into_octets(self) -> Octs
|
||||
where
|
||||
Octs: Sized,
|
||||
{
|
||||
self.octets
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u8]
|
||||
where
|
||||
Octs: AsRef<[u8]>,
|
||||
{
|
||||
self.octets.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_slice_mut(&mut self) -> &mut [u8]
|
||||
where
|
||||
Octs: AsMut<[u8]>,
|
||||
{
|
||||
self.octets.as_mut()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> KeyTagIter
|
||||
where Octs: AsRef<[u8]> {
|
||||
KeyTagIter(self.octets.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
//--- AsRef, AsMut, Borrow, BorrowMut
|
||||
|
||||
impl<Octs: AsRef<[u8]>> AsRef<[u8]> for KeyTag<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for KeyTag<Octs> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsMut<[u8]>> AsMut<[u8]> for KeyTag<Octs> {
|
||||
impl<Octs: AsMut<[u8]> + ?Sized> AsMut<[u8]> for KeyTag<Octs> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> borrow::Borrow<[u8]> for KeyTag<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> borrow::Borrow<[u8]> for KeyTag<Octs> {
|
||||
fn borrow(&self) -> &[u8] {
|
||||
self.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsMut<[u8]> + AsRef<[u8]>> borrow::BorrowMut<[u8]> for KeyTag<Octs> {
|
||||
impl<Octs> borrow::BorrowMut<[u8]> for KeyTag<Octs>
|
||||
where
|
||||
Octs: AsMut<[u8]> + AsRef<[u8]> + ?Sized
|
||||
{
|
||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
||||
self.as_slice_mut()
|
||||
}
|
||||
@@ -88,7 +110,7 @@ impl<Octs: AsMut<[u8]> + AsRef<[u8]>> borrow::BorrowMut<[u8]> for KeyTag<Octs> {
|
||||
|
||||
//--- OptData
|
||||
|
||||
impl<Octs> OptData for KeyTag<Octs> {
|
||||
impl<Octs: ?Sized> OptData for KeyTag<Octs> {
|
||||
fn code(&self) -> OptionCode {
|
||||
OptionCode::KeyTag
|
||||
}
|
||||
@@ -108,7 +130,7 @@ impl<'a, Octs: Octets> ParseOptData<'a, Octs> for KeyTag<Octs::Range<'a>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> ComposeOptData for KeyTag<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> ComposeOptData for KeyTag<Octs> {
|
||||
fn compose_len(&self) -> u16 {
|
||||
self.octets.as_ref().len().try_into().expect("long option data")
|
||||
}
|
||||
@@ -123,7 +145,7 @@ impl<Octs: AsRef<[u8]>> ComposeOptData for KeyTag<Octs> {
|
||||
|
||||
//--- IntoIterator
|
||||
|
||||
impl<'a, Octs: AsRef<[u8]>> IntoIterator for &'a KeyTag<Octs> {
|
||||
impl<'a, Octs: AsRef<[u8]> + ?Sized> IntoIterator for &'a KeyTag<Octs> {
|
||||
type Item = u16;
|
||||
type IntoIter = KeyTagIter<'a>;
|
||||
|
||||
@@ -135,7 +157,7 @@ impl<'a, Octs: AsRef<[u8]>> IntoIterator for &'a KeyTag<Octs> {
|
||||
|
||||
//--- Display
|
||||
|
||||
impl<Octets: AsRef<[u8]>> fmt::Display for KeyTag<Octets> {
|
||||
impl<Octets: AsRef<[u8]> + ?Sized> fmt::Display for KeyTag<Octets> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut first = true;
|
||||
|
||||
@@ -154,23 +176,31 @@ impl<Octets: AsRef<[u8]>> fmt::Display for KeyTag<Octets> {
|
||||
|
||||
//--- PartialEq and Eq
|
||||
|
||||
impl<Octs: AsRef<[u8]>, Other: AsRef<[u8]>> PartialEq<Other> for KeyTag<Octs> {
|
||||
impl<Octs, Other> PartialEq<Other> for KeyTag<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn eq(&self, other: &Other) -> bool {
|
||||
self.as_slice().eq(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Eq for KeyTag<Octs> { }
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Eq for KeyTag<Octs> { }
|
||||
|
||||
//--- PartialOrd and Ord
|
||||
|
||||
impl<Octs: AsRef<[u8]>, Other: AsRef<[u8]>> PartialOrd<Other> for KeyTag<Octs> {
|
||||
impl<Octs, Other> PartialOrd<Other> for KeyTag<Octs>
|
||||
where
|
||||
Octs: AsRef<[u8]> + ?Sized,
|
||||
Other: AsRef<[u8]> + ?Sized,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Other) -> Option<Ordering> {
|
||||
self.as_slice().partial_cmp(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Ord for KeyTag<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Ord for KeyTag<Octs> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.as_slice().cmp(other.as_slice())
|
||||
}
|
||||
@@ -178,7 +208,7 @@ impl<Octs: AsRef<[u8]>> Ord for KeyTag<Octs> {
|
||||
|
||||
//--- Hash
|
||||
|
||||
impl<Octs: AsRef<[u8]>> hash::Hash for KeyTag<Octs> {
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for KeyTag<Octs> {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
self.as_slice().hash(state)
|
||||
}
|
||||
@@ -209,7 +239,7 @@ impl<'a> Iterator for KeyTagIter<'a> {
|
||||
|
||||
impl<'a, Target: Composer> OptBuilder<'a, Target> {
|
||||
pub fn key_tag(
|
||||
&mut self, tags: &impl AsRef<[u16]>
|
||||
&mut self, tags: &(impl AsRef<[u16]> + ?Sized)
|
||||
) -> Result<(), Target::AppendError> {
|
||||
self.push_raw_option(
|
||||
OptionCode::KeyTag,
|
||||
@@ -237,7 +267,7 @@ mod test {
|
||||
#[test]
|
||||
fn nsid_compose_parse() {
|
||||
test_option_compose_parse(
|
||||
&KeyTag::new("fooo"),
|
||||
&KeyTag::from_octets("fooo"),
|
||||
|parser| KeyTag::parse(parser)
|
||||
);
|
||||
}
|
||||
|
||||
+6
-2
@@ -8,12 +8,12 @@ macro_rules! rdata_types {
|
||||
$module:ident::{
|
||||
$(
|
||||
zone {
|
||||
$( $mtype:ident $( < $( $mn:ident ),* > )*, )*
|
||||
$( $mtype:ident $( < $( $mn:ident ),* > ),* $(,)? )*
|
||||
}
|
||||
)*
|
||||
$(
|
||||
pseudo {
|
||||
$( $ptype:ident $( < $( $pn:ident ),* > )*, )*
|
||||
$( $ptype:ident $( < $( $pn:ident ),* > ),* $(,)? )*
|
||||
}
|
||||
)*
|
||||
|
||||
@@ -26,6 +26,10 @@ macro_rules! rdata_types {
|
||||
};
|
||||
)*
|
||||
|
||||
$(
|
||||
pub mod $module;
|
||||
)*
|
||||
|
||||
use crate::base::name::{ParsedDname, PushError, ToDname};
|
||||
use crate::base::wire::Composer;
|
||||
use crate::base::rdata::ComposeRecordData;
|
||||
|
||||
+7
-19
@@ -47,20 +47,10 @@
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
pub mod rfc1035;
|
||||
pub mod rfc2782;
|
||||
pub mod rfc2845;
|
||||
pub mod rfc3596;
|
||||
pub mod rfc4034;
|
||||
pub mod rfc5155;
|
||||
pub mod rfc6672;
|
||||
pub mod rfc7344;
|
||||
pub mod svcb;
|
||||
|
||||
// The rdata_types! macro (defined in self::macros) re-exports the record data
|
||||
// types here and creates the ZoneRecordData and AllRecordData enums
|
||||
// containing all record types that can appear in a zone and all record
|
||||
// types that exist.
|
||||
// The rdata_types! macro (defined in self::macros) defines the modules
|
||||
// containing the record data types, re-exports those here, and creates the
|
||||
// ZoneRecordData and AllRecordData enums containing all record types that
|
||||
// can appear in a zone file and all record types that exist.
|
||||
//
|
||||
// All record data types listed here MUST have the same name as the
|
||||
// `Rtype` variant they implement – some of the code implemented by the macro
|
||||
@@ -69,10 +59,8 @@ pub mod svcb;
|
||||
// Add any new module here and then add all record types in that module that
|
||||
// can appear in zone files under "zone" and all others under "pseudo".
|
||||
// Your type can be generic over an octet type "O" and a domain name type "N".
|
||||
// Add these as needed.
|
||||
//
|
||||
// Each type entry has to be followed by a comma, even the last one. The macro
|
||||
// is messy enough as it is ...
|
||||
// Add these as needed. Trait bounds on them differ for different methods, so
|
||||
// check the bounds on ZoneRecordData and AllRecordData if there are errors.
|
||||
rdata_types! {
|
||||
rfc1035::{
|
||||
zone {
|
||||
@@ -92,7 +80,7 @@ rdata_types! {
|
||||
Txt<O>,
|
||||
}
|
||||
pseudo {
|
||||
Null<O>,
|
||||
Null<O>
|
||||
}
|
||||
}
|
||||
rfc2782::{
|
||||
|
||||
+76
-39
@@ -1553,11 +1553,11 @@ impl<N: fmt::Display> fmt::Display for Soa<N> {
|
||||
///
|
||||
/// The Txt record type is defined in RFC 1035, section 3.3.14.
|
||||
#[derive(Clone)]
|
||||
pub struct Txt<Octs>(Octs);
|
||||
pub struct Txt<Octs: ?Sized>(Octs);
|
||||
|
||||
impl<Octs: FromBuilder> Txt<Octs> {
|
||||
/// Creates a new Txt record from a single character string.
|
||||
pub fn try_from_slice(text: &[u8]) -> Result<Self, ShortBuf>
|
||||
pub fn build_from_slice(text: &[u8]) -> Result<Self, ShortBuf>
|
||||
where
|
||||
<Octs as FromBuilder>::Builder:
|
||||
EmptyBuilder + AsRef<[u8]> + AsMut<[u8]>,
|
||||
@@ -1568,19 +1568,77 @@ impl<Octs: FromBuilder> Txt<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Txt<Octs> {
|
||||
/// Creates a new TXT record from its encoded content.
|
||||
pub fn from_octets(octets: Octs) -> Result<Self, CharStrError> {
|
||||
let mut tmp = octets.as_ref();
|
||||
while !tmp.is_empty() {
|
||||
if tmp.len() <= tmp[0] as usize {
|
||||
return Err(CharStrError);
|
||||
}
|
||||
tmp = &tmp[(tmp[0] as usize) + 1..];
|
||||
}
|
||||
Ok(Txt(octets))
|
||||
impl<Octs> Txt<Octs> {
|
||||
/// Creates new TXT record data from its encoded content.
|
||||
pub fn from_octets(octets: Octs) -> Result<Self, CharStrError>
|
||||
where
|
||||
Octs: AsRef<[u8]>
|
||||
{
|
||||
Txt::check_slice(octets.as_ref())?;
|
||||
Ok(unsafe { Txt::from_octets_unchecked(octets) })
|
||||
}
|
||||
|
||||
/// Creates new TXT record data without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The passed octets must contain correctly encoded TXT record data,
|
||||
/// that is a sequence of encoded character strings.
|
||||
unsafe fn from_octets_unchecked(octets: Octs) -> Self {
|
||||
Txt(octets)
|
||||
}
|
||||
|
||||
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
|
||||
parser: &mut Parser<'a, Src>,
|
||||
) -> Result<Self, ParseError>
|
||||
where Octs: AsRef<[u8]> {
|
||||
let len = parser.remaining();
|
||||
let text = parser.parse_octets(len)?;
|
||||
let mut tmp = Parser::from_ref(text.as_ref());
|
||||
while tmp.remaining() != 0 {
|
||||
CharStr::skip(&mut tmp)?
|
||||
}
|
||||
Ok(Txt(text))
|
||||
}
|
||||
|
||||
pub fn scan<S: Scanner<Octets = Octs>>(
|
||||
scanner: &mut S,
|
||||
) -> Result<Self, S::Error> {
|
||||
scanner.scan_charstr_entry().map(Txt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Txt<[u8]> {
|
||||
/// Creates new TXT record data on an octets slice.
|
||||
pub fn from_slice(slice: &[u8]) -> Result<&Self, CharStrError> {
|
||||
Txt::check_slice(slice)?;
|
||||
Ok(unsafe { Txt::from_slice_unchecked(slice) })
|
||||
}
|
||||
|
||||
/// Creates new TXT record data on an octets slice without checking.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The passed octets must contain correctly encoded TXT record data,
|
||||
/// that is a sequence of encoded character strings.
|
||||
unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
|
||||
unsafe { &*(slice as *const [u8] as *const Self) }
|
||||
}
|
||||
|
||||
/// Checks that a slice contains correctly encoded TXT data.
|
||||
fn check_slice(mut slice: &[u8]) -> Result<(), CharStrError> {
|
||||
while let Some(&len) = slice.first() {
|
||||
let len = usize::from(len);
|
||||
if slice.len() <= len {
|
||||
return Err(CharStrError);
|
||||
}
|
||||
slice = &slice[len + 1..];
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]> + ?Sized> Txt<Octs> {
|
||||
/// Returns an iterator over the text items.
|
||||
///
|
||||
/// The Txt format contains one or more length-delimited byte strings.
|
||||
@@ -1593,8 +1651,9 @@ impl<Octs: AsRef<[u8]>> Txt<Octs> {
|
||||
TxtCharStrIter(Parser::from_ref(self.0.as_ref()))
|
||||
}
|
||||
|
||||
/// Returns the content if it consists of a single character string.
|
||||
pub fn as_flat_slice(&self) -> Option<&[u8]> {
|
||||
if self.0.as_ref()[0] as usize == self.0.as_ref().len() - 1 {
|
||||
if usize::from(self.0.as_ref()[0]) == self.0.as_ref().len() - 1 {
|
||||
Some(&self.0.as_ref()[1..])
|
||||
} else {
|
||||
None
|
||||
@@ -1642,28 +1701,6 @@ impl<Octs: AsRef<[u8]>> Txt<Octs> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs> Txt<Octs> {
|
||||
pub fn scan<S: Scanner<Octets = Octs>>(
|
||||
scanner: &mut S,
|
||||
) -> Result<Self, S::Error> {
|
||||
scanner.scan_charstr_entry().map(Txt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Octs: AsRef<[u8]>> Txt<Octs> {
|
||||
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
|
||||
parser: &mut Parser<'a, Src>,
|
||||
) -> Result<Self, ParseError> {
|
||||
let len = parser.remaining();
|
||||
let text = parser.parse_octets(len)?;
|
||||
let mut tmp = Parser::from_ref(text.as_ref());
|
||||
while tmp.remaining() != 0 {
|
||||
CharStr::skip(&mut tmp)?
|
||||
}
|
||||
Ok(Txt(text))
|
||||
}
|
||||
}
|
||||
|
||||
impl<SrcOcts> Txt<SrcOcts> {
|
||||
pub(super) fn convert_octets<Target: OctetsFrom<SrcOcts>>(
|
||||
self,
|
||||
@@ -2287,19 +2324,19 @@ mod test {
|
||||
#[test]
|
||||
fn txt_from_slice() {
|
||||
let short = b"01234";
|
||||
let txt: Txt<Vec<u8>> = Txt::try_from_slice(short).unwrap();
|
||||
let txt: Txt<Vec<u8>> = Txt::build_from_slice(short).unwrap();
|
||||
assert_eq!(Some(&short[..]), txt.as_flat_slice());
|
||||
assert_eq!(short.to_vec(), txt.text::<Vec<u8>>());
|
||||
|
||||
// One full slice
|
||||
let full = short.repeat(51);
|
||||
let txt: Txt<Vec<u8>> = Txt::try_from_slice(&full).unwrap();
|
||||
let txt: Txt<Vec<u8>> = Txt::build_from_slice(&full).unwrap();
|
||||
assert_eq!(Some(&full[..]), txt.as_flat_slice());
|
||||
assert_eq!(full.to_vec(), txt.text::<Vec<u8>>());
|
||||
|
||||
// Two slices: 255, 5
|
||||
let long = short.repeat(52);
|
||||
let txt: Txt<Vec<u8>> = Txt::try_from_slice(&long).unwrap();
|
||||
let txt: Txt<Vec<u8>> = Txt::build_from_slice(&long).unwrap();
|
||||
assert_eq!(None, txt.as_flat_slice());
|
||||
assert_eq!(long.to_vec(), txt.text::<Vec<u8>>());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user