nomilo/src/resources/dns/internal/base.rs

195 lines
4.2 KiB
Rust

use std::{fmt, ops::Deref};
use domain::base::scan::Symbol;
use serde::{Serialize, Deserialize, Serializer};
#[derive(Clone, Debug, Deserialize)]
pub struct Label {
label: String
}
impl Label {
pub fn new(label: String) -> Self {
Label {
label,
}
}
}
impl Serialize for Label {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl fmt::Display for Label {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.label)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
pub struct Name {
name: String
}
impl Name {
pub fn new(name: String) -> Self {
Name {
name,
}
}
pub fn ends_with(&self, other: &Name) -> bool {
self.name == other.name || self.name.ends_with(&(String::from(".") + &other.name))
}
}
impl Serialize for Name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl fmt::Display for Name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
impl Ord for Name {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let mut labels = self.name.split('.').rev();
let mut other_labels = other.name.split('.').rev();
loop {
match (labels.next(), other_labels.next()) {
(Some(label), Some(other_label)) => match label.cmp(other_label) {
std::cmp::Ordering::Equal => (),
res => return res,
},
(None, Some(_)) => return std::cmp::Ordering::Less,
(Some(_), None) => return std::cmp::Ordering::Greater,
(None, None) => return std::cmp::Ordering::Equal,
}
}
}
}
impl PartialOrd for Name {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Eq, PartialEq)]
pub enum Rtype {
A,
Aaaa,
Cname,
Mx,
Ns,
Ptr,
Soa,
Srv,
Txt
}
impl Rtype {
pub fn value(&self) -> u16 {
match self {
Rtype::A => 1,
Rtype::Aaaa => 28,
Rtype::Cname => 5,
Rtype::Mx => 15,
Rtype::Ns => 2,
Rtype::Ptr => 12,
Rtype::Soa => 6,
Rtype::Srv => 33,
Rtype::Txt => 16,
}
}
}
impl Ord for Rtype {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value().cmp(&other.value())
}
}
impl PartialOrd for Rtype {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct Text {
pub data: Vec<u8>
}
impl Text {
pub fn new(data: Vec<u8>) -> Self {
Text {
data,
}
}
pub fn bytes(self) -> Vec<u8> {
self.data
}
pub fn add_prefix_if_not_present<B: AsRef<[u8]>>(&self, prefix: B) -> Text {
let mut data = Vec::new();
data.extend_from_slice(prefix.as_ref());
if !self.data.starts_with(prefix.as_ref()) {
data.extend_from_slice(&self.data);
}
Text::new(data)
}
pub fn strip_prefix<B: AsRef<[u8]>>(&self, prefix: B) -> Text{
self.data.strip_prefix(prefix.as_ref())
.map(|data| Text::new(data.into()))
.unwrap_or_else(|| self.clone())
}
}
impl Deref for Text {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl Serialize for Text {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl fmt::Display for Text {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for c in &self.data {
// Escapes '\' and non printable chars
let c = Symbol::display_from_octet(*c);
write!(f, "{}", c)?;
}
Ok(())
}
}