use super::{ResolveAs, ResolvedSubnet};
use crate::identifier_match::{IdentifierMatch, match_identifier};
use crate::subnet_catalog::{CatalogError, RawSubnetCatalog, parse_principal};
use std::collections::BTreeSet;
impl RawSubnetCatalog {
pub fn resolve_principal_or_prefix(
&self,
input: &str,
forced: Option<ResolveAs>,
) -> Result<ResolvedSubnet, CatalogError> {
if let Ok(principal) = parse_principal(input, "principal") {
return self.resolve_parsed_principal(&principal, forced);
}
self.resolve_principal_prefix(input, forced)
}
pub fn resolve_principal_prefix(
&self,
input: &str,
forced: Option<ResolveAs>,
) -> Result<ResolvedSubnet, CatalogError> {
let prefix = input.trim().to_ascii_lowercase();
if prefix.is_empty() {
return Err(CatalogError::PrincipalPrefixNotFound { prefix });
}
let identifiers = self
.subnets
.iter()
.filter(|_| forced != Some(ResolveAs::Canister))
.map(|subnet| subnet.subnet_principal.as_str())
.collect::<BTreeSet<_>>();
let matched = match match_identifier(identifiers.into_iter(), |value| value, None, &prefix)
{
IdentifierMatch::Prefix(subnet) => subnet,
IdentifierMatch::Missing => {
return Err(CatalogError::PrincipalPrefixNotFound { prefix });
}
IdentifierMatch::Ambiguous(matches) => {
return Err(CatalogError::AmbiguousPrincipalPrefix {
prefix,
matches: matches
.into_iter()
.map(|subnet| format!("subnet:{subnet}"))
.collect(),
});
}
IdentifierMatch::Exact(_) => {
unreachable!("prefix lookup supplies no exact identifier")
}
};
let mut resolved = self.resolve_known_subnet(matched)?;
resolved.input_principal = input.to_string();
resolved.resolved_from = "subnet_principal_prefix".to_string();
Ok(resolved)
}
}