nonymous 0.7.0

DNS protocol and algorithm library
Documentation
use core::marker::PhantomData;

use crate::core::{Class, Type};
use crate::emit::message::{ArSection, ArWithOpt, MessageBuilder, MessageError};
use crate::emit::name::NameError;
use crate::emit::record::{RecordBuilder, RecordData, RecordError};
use crate::emit::{Buffer, Builder, ChildBuilder, PushBuilder, Sink};

error!(ExtensionError, Record, Name);
/// failed to emit OPT RR
#[derive(Debug, displaydoc::Display)]
#[prefix_enum_doc_attributes]
pub enum ExtensionError {
    /// too many records in additional section
    ArTooManyRecords,

    /// error while creating record
    Record(RecordError),

    /// error while emitting record NAME
    Name(NameError),
}

/// # Up transitions
/// * [`finish`][`ExtensionBuilder::finish`]
#[must_use]
pub struct ExtensionBuilder<'b, P> {
    buffer: PhantomData<&'b mut dyn Buffer>,
    parent: RecordBuilder<'b, P, RecordData>,
}

impl<'b, P: Builder<'b>> ChildBuilder<'b, MessageBuilder<'b, P, ArSection>>
    for ExtensionBuilder<'b, MessageBuilder<'b, P, ArSection>>
{
    fn parent(&mut self) -> &mut MessageBuilder<'b, P, ArSection> {
        self.parent.parent()
    }
}

impl<'b, P: Builder<'b>> PushBuilder<'b, MessageBuilder<'b, P, ArSection>>
    for ExtensionBuilder<'b, MessageBuilder<'b, P, ArSection>>
{
    type Error = ExtensionError;
    fn push(parent: MessageBuilder<'b, P, ArSection>) -> Result<Self, ExtensionError> {
        Ok(Self {
            buffer: PhantomData,
            parent: parent
                .record()
                .map_err(|_| ExtensionError::ArTooManyRecords)?
                .name()
                .map_err(ExtensionError::Record)?
                .try_into_rdata()
                .map_err(ExtensionError::Name)?
                .r#type(Type::new(41)),
        })
    }
}

builder! {
    <'b, P> ExtensionBuilder {
        Builder;
        @ <P>:
        pub fn udp(mut self, value: u16) -> Self = {
            self.parent = self.parent.class(Class::new(value));

            self
        }
        pub fn version(mut self, value: u8) -> Self = {
            let offset = self.parent.name_len() + 5;
            self.sink().inner_mut()[offset] = value;

            self
        }
        pub fn r#do(mut self, value: bool) -> Self = {
            let offset = self.parent.name_len() + 6;
            self.sink().inner_mut()[offset] = u8::from(value) << 7;

            self
        }
    }
}

/// <h2>Up transitions</h2>
impl<__> ExtensionBuilder<'_, __> {}
builder! {
    <'b, P> ExtensionBuilder {
        @ <MessageBuilder<'b, P, ArSection>>:
            /// Finish building the EDNS OPT RR and return to the parent builder.
            pub fn finish(mut self) -> Result<MessageBuilder<'b, P, ArWithOpt>, MessageError> = {
                let extended_part = self.parent().get_rcode().extended_part();
                let offset = self.parent.name_len() + 4;
                self.sink().inner_mut()[offset] = extended_part;
                Ok(self
                    .parent
                    .finish()
                    .map_err(ExtensionError::Record)
                    .map_err(MessageError::Extension)?
                    .into())
            }
    }
}