nonymous 0.7.0

DNS protocol and algorithm library
Documentation
//! Strongly typed RDATA access, across both views and owned types.
//!
//! ```
//! # #[macro_use] extern crate nonymous;
//! # declare_any_error!(AnyError);
//! use nonymous::rdata::A;
//! use nonymous::view::{Record, View};
//! use nonymous::fmt::Plain;
//! let record = b"\0\x00\x01\x00\x01\0\0\0\0\x00\x04\xC0\x00\x02\x01";
//! let record = Record::view(record, ..)?.0;
//!
//! // Prints: 192.0.2.1
//! dbg!(record.rdata_as_view::<A>()?.to_ipv4_addr());
//! # Ok::<(), AnyError>(())
//! ```

pub mod view;

use crate::core::{Class, Type};
use crate::rdata::class::{GenericClass, InClass};
use crate::rdata::view::error::RdataError;
use crate::view::{View, ViewToOwned};

use core::marker::PhantomData;
use core::net::{Ipv4Addr, Ipv6Addr};

/// Any marker type that pairs a TYPE with a CLASS.
pub trait ClassType {
    const CLASS: Class;
    const TYPE: Type;
    type View<'s>: RdataView<'s>;
}
/// RDATA views must implement this trait, which is [`View`] with additional requirements.
pub trait RdataView<'s>: View<'s, Error = RdataError> {}

/// Marker type for NS records. Generic across all classes.
pub struct Ns<C: GenericClass = InClass>(PhantomData<C>);
impl<C: GenericClass> ClassType for Ns<C> {
    const CLASS: Class = C::CLASS;

    const TYPE: Type = Type::NS;

    type View<'s> = crate::rdata::view::Ns<'s>;
}
impl<'s> RdataView<'s> for crate::rdata::view::Ns<'s> {}
#[cfg(feature = "alloc")]
impl ViewToOwned<crate::name::NameBuf> for crate::rdata::view::Ns<'_> {
    fn to_owned(&self) -> crate::name::NameBuf {
        self.name().into()
    }
}

/// Marker type for CNAME records. Generic across all classes.
pub struct Cname<C: GenericClass = InClass>(PhantomData<C>);
impl<C: GenericClass> ClassType for Cname<C> {
    const CLASS: Class = C::CLASS;

    const TYPE: Type = Type::CNAME;

    type View<'s> = crate::rdata::view::Cname<'s>;
}
impl<'s> RdataView<'s> for crate::rdata::view::Cname<'s> {}
#[cfg(feature = "alloc")]
impl ViewToOwned<crate::name::NameBuf> for crate::rdata::view::Cname<'_> {
    fn to_owned(&self) -> crate::name::NameBuf {
        self.name().into()
    }
}

/// Marker type for PTR records. Generic across all classes.
pub struct Ptr<C: GenericClass = InClass>(PhantomData<C>);
impl<C: GenericClass> ClassType for Ptr<C> {
    const CLASS: Class = C::CLASS;

    const TYPE: Type = Type::PTR;

    type View<'s> = crate::rdata::view::Ptr<'s>;
}
impl<'s> RdataView<'s> for crate::rdata::view::Ptr<'s> {}
#[cfg(feature = "alloc")]
impl ViewToOwned<crate::name::NameBuf> for crate::rdata::view::Ptr<'_> {
    fn to_owned(&self) -> crate::name::NameBuf {
        self.name().into()
    }
}

/// Marker type for A records. Currently implemented for IN class only.
pub struct A<C: GenericClass = InClass>(PhantomData<C>);
impl ClassType for A<InClass> {
    const CLASS: Class = Class::IN;
    const TYPE: Type = Type::A;
    type View<'s> = crate::rdata::view::A<'s>;
}
impl<'s> RdataView<'s> for crate::rdata::view::A<'s> {}
impl ViewToOwned<Ipv4Addr> for crate::rdata::view::A<'_> {
    fn to_owned(&self) -> Ipv4Addr {
        self.to_ipv4_addr()
    }
}

/// Marker type for AAAA records. Currently implemented for IN class only.
pub struct Aaaa<C: GenericClass = InClass>(PhantomData<C>);
impl ClassType for Aaaa<InClass> {
    const CLASS: Class = Class::IN;
    const TYPE: Type = Type::AAAA;
    type View<'s> = crate::rdata::view::Aaaa<'s>;
}
impl<'s> RdataView<'s> for crate::rdata::view::Aaaa<'s> {}
impl ViewToOwned<Ipv6Addr> for crate::rdata::view::Aaaa<'_> {
    fn to_owned(&self) -> Ipv6Addr {
        self.to_ipv6_addr()
    }
}

/// Marker types for CLASSes, such as the [`InClass`].
pub mod class {
    use crate::core::Class;

    pub trait GenericClass {
        const CLASS: Class;
    }

    #[derive(Clone, Debug)]
    pub struct InClass;
    impl GenericClass for InClass {
        const CLASS: Class = Class::IN;
    }
}