use core::{
borrow::{Borrow, BorrowMut},
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
ops::{Deref, DerefMut},
str::FromStr,
};
use crate::{
new::base::{
build::{BuildInMessage, NameCompressor},
parse::{ParseMessageBytes, SplitMessageBytes},
wire::{
BuildBytes, ParseBytes, ParseError, SplitBytes, TruncationError,
},
},
utils::dst::{UnsizedCopy, UnsizedCopyFrom},
};
use super::{LabelIter, NameBuf, NameParseError};
#[derive(UnsizedCopy)]
#[repr(transparent)]
pub struct RevName([u8]);
impl RevName {
pub const MAX_SIZE: usize = 255;
pub const ROOT: &'static Self = {
unsafe { Self::from_bytes_unchecked(&[0u8]) }
};
}
impl RevName {
pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
core::mem::transmute(bytes)
}
pub unsafe fn from_bytes_unchecked_mut(bytes: &mut [u8]) -> &mut Self {
core::mem::transmute(bytes)
}
}
impl RevName {
#[allow(clippy::len_without_is_empty)]
pub const fn len(&self) -> usize {
self.0.len()
}
pub const fn is_root(&self) -> bool {
self.0.len() == 1
}
pub const fn as_bytes(&self) -> &[u8] {
&self.0
}
pub const fn labels(&self) -> LabelIter<'_> {
unsafe { LabelIter::new_unchecked(self.as_bytes()) }
}
}
impl BuildInMessage for RevName {
fn build_in_message(
&self,
contents: &mut [u8],
start: usize,
compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
if let Some((rest, addr)) =
compressor.compress_revname(&contents[..start], self)
{
let end = start + rest.len() + 2;
let buffer =
contents.get_mut(start..end).ok_or(TruncationError)?;
let (mut buffer, pointer) = buffer.split_at_mut(rest.len());
let labels = unsafe { LabelIter::new_unchecked(rest) };
for label in labels {
let label_buffer;
let offset = buffer.len() - label.as_bytes().len();
(buffer, label_buffer) = buffer.split_at_mut(offset);
label_buffer.copy_from_slice(label.as_bytes());
}
let addr = (addr + 0xC00C).to_be_bytes();
pointer.copy_from_slice(&addr);
Ok(end)
} else {
let bytes = contents.get_mut(start..).ok_or(TruncationError)?;
self.build_bytes(bytes)?;
Ok(start + self.len())
}
}
}
impl BuildBytes for RevName {
fn build_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
if bytes.len() < self.len() {
return Err(TruncationError);
}
let (mut buffer, rest) = bytes.split_at_mut(self.len());
for label in self.labels() {
let label_buffer;
let offset = buffer.len() - label.as_bytes().len();
(buffer, label_buffer) = buffer.split_at_mut(offset);
label_buffer.copy_from_slice(label.as_bytes());
}
Ok(rest)
}
fn built_bytes_size(&self) -> usize {
self.len()
}
}
#[cfg(feature = "alloc")]
impl Clone for alloc::boxed::Box<RevName> {
fn clone(&self) -> Self {
(*self).unsized_copy_into()
}
}
impl PartialEq for RevName {
fn eq(&self, that: &Self) -> bool {
let this = self.as_bytes().iter().map(u8::to_ascii_lowercase);
let that = that.as_bytes().iter().map(u8::to_ascii_lowercase);
this.eq(that)
}
}
impl Eq for RevName {}
impl PartialOrd for RevName {
fn partial_cmp(&self, that: &Self) -> Option<Ordering> {
Some(self.cmp(that))
}
}
impl Ord for RevName {
fn cmp(&self, that: &Self) -> Ordering {
self.labels().cmp(that.labels())
}
}
impl Hash for RevName {
fn hash<H: Hasher>(&self, state: &mut H) {
for byte in self.as_bytes() {
state.write_u8(byte.to_ascii_lowercase())
}
}
}
impl fmt::Debug for RevName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("RevName(")?;
let mut first = true;
self.labels().try_for_each(|label| {
if !first {
f.write_str(".")?;
} else {
first = false;
}
fmt::Display::fmt(&label, f)
})?;
f.write_str(")")
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for RevName {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
NameBuf::from(RevNameBuf::copy_from(self)).serialize(serializer)
}
}
#[derive(Clone)]
#[repr(C)] pub struct RevNameBuf {
offset: u8,
buffer: [u8; 255],
}
impl RevNameBuf {
const fn empty() -> Self {
Self {
offset: 255,
buffer: [0; 255],
}
}
pub fn copy_from(name: &RevName) -> Self {
let offset = 255 - name.len() as u8;
let mut buffer = [0u8; 255];
buffer[offset as usize..].copy_from_slice(name.as_bytes());
Self { offset, buffer }
}
}
impl UnsizedCopyFrom for RevNameBuf {
type Source = RevName;
fn unsized_copy_from(value: &Self::Source) -> Self {
Self::copy_from(value)
}
}
impl<'a> SplitMessageBytes<'a> for RevNameBuf {
fn split_message_bytes(
contents: &'a [u8],
start: usize,
) -> Result<(Self, usize), ParseError> {
let mut buffer = Self::empty();
let bytes = contents.get(start..).ok_or(ParseError)?;
let (mut pointer, rest) = parse_segment(bytes, &mut buffer)?;
let orig_end = contents.len() - rest.len();
let mut old_start = start;
while let Some(start) = pointer.map(usize::from) {
let start = start.checked_sub(12).ok_or(ParseError)?;
if start >= old_start {
return Err(ParseError);
}
let bytes = contents.get(start..).ok_or(ParseError)?;
(pointer, _) = parse_segment(bytes, &mut buffer)?;
old_start = start;
continue;
}
Ok((buffer, orig_end))
}
}
impl<'a> ParseMessageBytes<'a> for RevNameBuf {
fn parse_message_bytes(
contents: &'a [u8],
start: usize,
) -> Result<Self, ParseError> {
let mut buffer = Self::empty();
let bytes = contents.get(start..).ok_or(ParseError)?;
let (mut pointer, rest) = parse_segment(bytes, &mut buffer)?;
if !rest.is_empty() {
return Err(ParseError);
}
let mut old_start = start;
while let Some(start) = pointer.map(usize::from) {
let start = start.checked_sub(12).ok_or(ParseError)?;
if start >= old_start {
return Err(ParseError);
}
let bytes = contents.get(start..).ok_or(ParseError)?;
(pointer, _) = parse_segment(bytes, &mut buffer)?;
old_start = start;
continue;
}
Ok(buffer)
}
}
fn parse_segment<'a>(
mut bytes: &'a [u8],
buffer: &mut RevNameBuf,
) -> Result<(Option<u16>, &'a [u8]), ParseError> {
loop {
match *bytes {
[0, ref rest @ ..] => {
buffer.prepend_bytes(&[0u8]);
return Ok((None, rest));
}
[l, ..] if l < 64 => {
if bytes.len() < 1 + l as usize {
return Err(ParseError);
} else if buffer.offset < 2 + l {
return Err(ParseError);
}
let (label, rest) = bytes.split_at(1 + l as usize);
buffer.prepend_bytes(label);
bytes = rest;
}
[hi, lo, ref rest @ ..] if hi >= 0xC0 => {
let pointer = u16::from_be_bytes([hi, lo]);
return Ok((Some(pointer & 0x3FFF), rest));
}
_ => return Err(ParseError),
}
}
}
impl BuildInMessage for RevNameBuf {
fn build_in_message(
&self,
contents: &mut [u8],
start: usize,
compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
RevName::build_in_message(self, contents, start, compressor)
}
}
impl<'a> SplitBytes<'a> for RevNameBuf {
fn split_bytes(bytes: &'a [u8]) -> Result<(Self, &'a [u8]), ParseError> {
let mut buffer = Self::empty();
let (pointer, rest) = parse_segment(bytes, &mut buffer)?;
if pointer.is_some() {
return Err(ParseError);
}
Ok((buffer, rest))
}
}
impl<'a> ParseBytes<'a> for RevNameBuf {
fn parse_bytes(bytes: &'a [u8]) -> Result<Self, ParseError> {
match Self::split_bytes(bytes) {
Ok((this, &[])) => Ok(this),
_ => Err(ParseError),
}
}
}
impl BuildBytes for RevNameBuf {
fn build_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
(**self).build_bytes(bytes)
}
fn built_bytes_size(&self) -> usize {
(**self).built_bytes_size()
}
}
impl RevNameBuf {
fn prepend_bytes(&mut self, bytes: &[u8]) {
self.offset -= bytes.len() as u8;
self.buffer[self.offset as usize..][..bytes.len()]
.copy_from_slice(bytes);
}
}
impl From<NameBuf> for RevNameBuf {
fn from(value: NameBuf) -> Self {
Self::parse_bytes(value.as_bytes())
.expect("a 'NameBuf' is a correctly encoded domain name")
}
}
impl From<RevNameBuf> for NameBuf {
fn from(value: RevNameBuf) -> Self {
let mut buffer = [0u8; 255];
let len = buffer.len()
- value
.build_bytes(&mut buffer)
.expect("any domain name fits in 255 bytes")
.len();
Self::parse_bytes(&buffer[..len])
.expect("a 'RevNameBuf' is a correctly encoded domain name")
}
}
impl Deref for RevNameBuf {
type Target = RevName;
fn deref(&self) -> &Self::Target {
let name = &self.buffer[self.offset as usize..];
unsafe { RevName::from_bytes_unchecked(name) }
}
}
impl DerefMut for RevNameBuf {
fn deref_mut(&mut self) -> &mut Self::Target {
let name = &mut self.buffer[self.offset as usize..];
unsafe { RevName::from_bytes_unchecked_mut(name) }
}
}
impl Borrow<RevName> for RevNameBuf {
fn borrow(&self) -> &RevName {
self
}
}
impl BorrowMut<RevName> for RevNameBuf {
fn borrow_mut(&mut self) -> &mut RevName {
self
}
}
impl AsRef<RevName> for RevNameBuf {
fn as_ref(&self) -> &RevName {
self
}
}
impl AsMut<RevName> for RevNameBuf {
fn as_mut(&mut self) -> &mut RevName {
self
}
}
impl PartialEq for RevNameBuf {
fn eq(&self, that: &Self) -> bool {
**self == **that
}
}
impl Eq for RevNameBuf {}
impl PartialOrd for RevNameBuf {
fn partial_cmp(&self, that: &Self) -> Option<Ordering> {
Some(self.cmp(that))
}
}
impl Ord for RevNameBuf {
fn cmp(&self, that: &Self) -> Ordering {
(**self).cmp(&**that)
}
}
impl Hash for RevNameBuf {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl fmt::Debug for RevNameBuf {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl RevNameBuf {
pub fn parse_str(s: &[u8]) -> Result<(Self, &[u8]), NameParseError> {
NameBuf::parse_str(s).map(|(this, rest)| (this.into(), rest))
}
}
impl FromStr for RevNameBuf {
type Err = NameParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match Self::parse_str(s.as_bytes()) {
Ok((this, &[])) => Ok(this),
Ok(_) => Err(NameParseError::InvalidChar),
Err(err) => Err(err),
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for RevNameBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
(**self).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Deserialize<'a> for RevNameBuf {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'a>,
{
NameBuf::deserialize(deserializer).map(|this| this.into())
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Deserialize<'a> for std::boxed::Box<RevName> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'a>,
{
RevNameBuf::deserialize(deserializer)
.map(|this| this.unsized_copy_into())
}
}