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);
#[derive(Debug, displaydoc::Display)]
#[prefix_enum_doc_attributes]
pub enum ExtensionError {
ArTooManyRecords,
Record(RecordError),
Name(NameError),
}
#[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
}
}
}
impl<__> ExtensionBuilder<'_, __> {}
builder! {
<'b, P> ExtensionBuilder {
@ <MessageBuilder<'b, P, ArSection>>:
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())
}
}
}