use super::codec::decode_event;
use super::codec::OnionCircuitEvent;
use super::reducer::OnionCircuitEffect;
use super::reducer::OnionCircuitReducer;
use super::reducer::OnionCircuitState;
use super::ONION_CIRCUIT_NAMESPACE;
use crate::extension::ext::Ctx;
use crate::extension::ext::Protocol;
use crate::extension::ext::Reject;
use crate::extension::ext::Transition;
use crate::extension::ext::Wire;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum OnionCircuitCapabilities {
Client,
Relay,
Exit,
RelayAndExit,
}
impl OnionCircuitCapabilities {
pub const fn from_registration(relay: bool, exit: bool) -> Self {
match (relay, exit) {
(false, false) => Self::Client,
(true, false) => Self::Relay,
(false, true) => Self::Exit,
(true, true) => Self::RelayAndExit,
}
}
pub const fn client() -> Self {
Self::Client
}
pub const fn relay() -> Self {
Self::Relay
}
pub const fn exit() -> Self {
Self::Exit
}
pub(super) const fn accepts_forward_layers(self) -> bool {
matches!(self, Self::Relay | Self::Exit | Self::RelayAndExit)
}
pub(super) const fn permits_relay_layer(self) -> bool {
matches!(self, Self::Relay | Self::RelayAndExit)
}
pub(super) const fn permits_exit_layer(self) -> bool {
matches!(self, Self::Exit | Self::RelayAndExit)
}
}
#[derive(Clone, Debug)]
pub struct OnionCircuitProtocol {
reducer: OnionCircuitReducer,
}
impl OnionCircuitProtocol {
pub fn new(capabilities: OnionCircuitCapabilities) -> Self {
Self {
reducer: OnionCircuitReducer::new(capabilities),
}
}
}
impl Protocol for OnionCircuitProtocol {
type State = OnionCircuitState;
type Event = OnionCircuitEvent;
type Effect = OnionCircuitEffect;
fn namespace(&self) -> &str {
ONION_CIRCUIT_NAMESPACE
}
fn init(&self) -> Self::State {
OnionCircuitState::default()
}
fn decode(&self, wire: Wire<'_>) -> std::result::Result<Self::Event, Reject> {
decode_event(wire)
}
fn step(
&self,
ctx: Ctx<'_, Self::State>,
event: Self::Event,
) -> Transition<Self::State, Self::Effect> {
self.reducer.apply(ctx.state, event.input)
}
}