ic-query 0.76.5

Internet Computer query library for CloudEngine, NNS, SNS, ICRC, system canisters, and public network metadata
Documentation
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 {
    /// Resolve an exact principal or a unique cached subnet principal prefix.
    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)
    }

    /// Resolve a unique prefix of a cached subnet principal.
    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)
    }
}