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:
Martin Hoffmann
2023-02-06 13:13:44 +01:00
committed by GitHub
parent 034adf2a28
commit 4d13b01022
13 changed files with 555 additions and 300 deletions
+73 -67
View File
@@ -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
View File
@@ -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.
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+11 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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>>());