use crate::context::CliContext;
use crate::error::CliError;
use crate::operator::{
parse_hop_token, resolve_socket, send_request, PathDirection, WireRequest, WireResponse,
};
use crate::prompt::PromptPlan;
use crate::report::PathReport;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathCommand {
Add {
socket: Option<String>,
hops: Vec<String>,
direction: Option<PathDirection>,
},
Discover {
socket: Option<String>,
bound: Option<u64>,
},
}
impl PathCommand {
#[must_use]
pub const fn prompt_plan(&self, _ctx: &CliContext<'_>) -> PromptPlan {
PromptPlan::None
}
}
pub(crate) fn execute(command: &PathCommand, ctx: &CliContext<'_>) -> Result<PathReport, CliError> {
match command {
PathCommand::Add {
socket,
hops,
direction,
} => {
if hops.is_empty() {
return Err(CliError::OperatorHygiene(
"--hop is required: an add_path needs at least one hop".to_string(),
));
}
let steps = hops
.iter()
.map(String::as_str)
.map(parse_hop_token)
.collect::<Result<Vec<_>, _>>()?;
let directions = direction
.as_ref()
.map(|direction| vec![direction.is_zfo(); steps.len()]);
let request = WireRequest::AddPath { steps, directions };
match call(ctx, socket.as_deref(), &request)? {
WireResponse::Ok { detail, .. } => Ok(PathReport::Added { detail }),
WireResponse::Err { error } => Err(CliError::OperatorRefused(error)),
}
}
PathCommand::Discover { socket, bound } => {
let request = WireRequest::Discover { bound: *bound };
match call(ctx, socket.as_deref(), &request)? {
WireResponse::Ok { detail, .. } => Ok(PathReport::Discovered { detail }),
WireResponse::Err { error } => Err(CliError::OperatorRefused(error)),
}
}
}
}
fn call(
ctx: &CliContext<'_>,
socket: Option<&str>,
request: &WireRequest,
) -> Result<WireResponse, CliError> {
let socket = resolve_socket(ctx.env(), socket);
send_request(&socket, request)
}