nonymous 0.7.0

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

use byteorder::{ByteOrder, NetworkEndian};

use crate::core::{Class, Type};
use crate::emit::message::{MessageBuilder, QuestionStep};
use crate::emit::name::{NameBuilder, NameError};
use crate::emit::{Buffer, Builder, ChildBuilder, GrowError, PushBuilder, Sink};

error!(QuestionError, Grow, Name);
/// failed to emit question
#[derive(Debug, displaydoc::Display)]
#[prefix_enum_doc_attributes]
pub enum QuestionError {
    /// not enough space
    Grow(GrowError),

    /// error while emitting name
    Name(NameError),
}

/// # Down transitions
/// * [`qname`][`QuestionBuilder::qname`]
/// # Up transitions
/// (see [`NameBuilder`])
#[must_use]
pub struct QuestionBuilder<'b, P> {
    buffer: PhantomData<&'b mut dyn Buffer>,
    parent: P,
}

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

impl<'b, P: Builder<'b>> PushBuilder<'b, P> for QuestionBuilder<'b, P> {
    type Error = QuestionError;
    fn push(parent: P) -> Result<Self, QuestionError> {
        Ok(Self {
            buffer: PhantomData,
            parent,
        })
    }
}

builder! {
    <'b, P> QuestionBuilder {
        Builder;
    }
}

/// <h2>Down transitions</h2>
impl<__> QuestionBuilder<'_, __> {}
builder! {
    <'b, P> QuestionBuilder {
        @ <P>:
            /// Start building the record’s QNAME.
            pub fn qname(mut self) = [push NameBuilder | QuestionError::Name] { self }
    }
}

// Helpers for up transitions
builder! {
    <'b, P> QuestionBuilder {
        @ <MessageBuilder<'b, P, Q>> [Q: QuestionStep]:
            /// Finish building the question and return to the message’s question section.
            pub(in crate::emit) fn finish(
                mut self,
                qtype: Type,
                qclass: Class,
            ) -> Result<MessageBuilder<'b, P, Q>, QuestionError> = {
                NetworkEndian::write_u16(
                    self.sink().grow_mut(2).map_err(QuestionError::Grow)?,
                    qtype.value(),
                );
                NetworkEndian::write_u16(
                    self.sink().grow_mut(2).map_err(QuestionError::Grow)?,
                    qclass.value(),
                );

                Ok(self.parent)
            }
    }
}