Skip to main content

canic_backup/plan/build/
selector.rs

1//! Module: plan::build::selector
2//!
3//! Responsibility: resolve operator backup selectors against registry entries.
4//! Does not own: registry discovery, plan construction, or target expansion.
5//! Boundary: returns one selected canister id or a typed plan error.
6
7use crate::{
8    plan::{BackupPlanError, validation::validate_nonempty},
9    registry::RegistryEntry,
10};
11
12use std::str::FromStr;
13
14use candid::Principal;
15
16/// Resolve an operator selector to one concrete live registry canister id.
17pub fn resolve_backup_selector(
18    registry: &[RegistryEntry],
19    selector: &str,
20) -> Result<String, BackupPlanError> {
21    validate_nonempty("selector", selector)?;
22    if Principal::from_str(selector).is_ok() {
23        return registry
24            .iter()
25            .find(|entry| entry.pid == selector)
26            .map(|entry| entry.pid.clone())
27            .ok_or_else(|| BackupPlanError::UnknownSelector(selector.to_string()));
28    }
29
30    let matches = registry
31        .iter()
32        .filter(|entry| entry.role.as_deref() == Some(selector))
33        .map(|entry| entry.pid.clone())
34        .collect::<Vec<_>>();
35    match matches.as_slice() {
36        [canister] => Ok(canister.clone()),
37        [] => Err(BackupPlanError::UnknownSelector(selector.to_string())),
38        _ => Err(BackupPlanError::AmbiguousSelector {
39            selector: selector.to_string(),
40            matches,
41        }),
42    }
43}