use educe::Educe;
use tor_cell::chancell::msg::PaddingNegotiate;
use super::padding;
macro_rules! define_channels_insns_and_automatic_impls { { $(
$( #[doc $($doc_attr:tt)*] )*
$( #[field $other_attr:meta] )*
$field:ident : $ty:ty
),* $(,)? } => {
#[derive(Debug, Educe, Clone, Eq, PartialEq)]
#[educe(Default)]
pub struct ChannelPaddingInstructions {
$(
$( #[doc $($doc_attr)*] )*
$( #[$other_attr] )*
pub(crate) $field: $ty,
)*
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct ChannelPaddingInstructionsUpdates {
$(
pub(crate) $field: Option<$ty>,
)*
}
impl ChannelPaddingInstructions {
#[must_use = "initial_update makes an updates message that must be sent to have effect"]
pub fn initial_update(&self) -> Option<ChannelPaddingInstructionsUpdates> {
let mut supposed = ChannelPaddingInstructions::default();
supposed.start_update()
$(
.$field(self.$field.clone())
)*
.finish()
}
}
impl<'c> ChannelPaddingInstructionsUpdatesBuilder<'c> {
$(
$( #[doc $($doc_attr)*] )*
pub fn $field(mut self, new_value: $ty) -> Self {
if &new_value != &self.insns.$field {
self
.update
.get_or_insert_with(|| Default::default())
.$field = Some(new_value.clone());
self.insns.$field = new_value;
}
self
}
)*
}
impl ChannelPaddingInstructionsUpdates {
pub fn combine(&mut self, more: &Self) {
$(
if let Some(new_value) = &more.$field {
self.$field = Some(new_value.clone());
}
)*
}
$(
#[cfg(feature = "testing")]
$( #[doc $($doc_attr)*] )*
pub fn $field(&self) -> Option<&$ty> {
self.$field.as_ref()
}
)*
}
} }
define_channels_insns_and_automatic_impls! {
padding_enable: bool,
#[field educe(Default(expression = "padding::Parameters::disabled()"))]
padding_parameters: padding::Parameters,
padding_negotiate: PaddingNegotiate,
}
pub struct ChannelPaddingInstructionsUpdatesBuilder<'c> {
insns: &'c mut ChannelPaddingInstructions,
update: Option<ChannelPaddingInstructionsUpdates>,
drop_bomb: bool,
}
impl ChannelPaddingInstructions {
pub fn start_update(&mut self) -> ChannelPaddingInstructionsUpdatesBuilder {
ChannelPaddingInstructionsUpdatesBuilder {
insns: self,
update: None,
drop_bomb: true,
}
}
}
impl<'c> Drop for ChannelPaddingInstructionsUpdatesBuilder<'c> {
fn drop(&mut self) {
assert!(
!self.drop_bomb,
"ChannelPaddingInstructionsUpdatesBuilder dropped"
);
}
}
impl<'c> ChannelPaddingInstructionsUpdatesBuilder<'c> {
#[must_use = "the update from finish() must be sent, to avoid losing insns changes"]
pub fn finish(mut self) -> Option<ChannelPaddingInstructionsUpdates> {
self.drop_bomb = false;
self.update.take()
}
}