canic_host/subnet_registry/
mod.rs1use crate::{
8 icp::{IcpCli, IcpCommandError},
9 registry::{RegistryEntry, RegistryParseError, parse_registry_entries},
10 replica_query::{self, ReplicaQueryError},
11};
12use std::{error::Error, fmt, path::Path};
13
14const CANIC_SUBNET_REGISTRY_METHOD: &str = "canic_subnet_registry";
15const ICP_JSON_OUTPUT: &str = "json";
16
17#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct SubnetRegistryQuery {
23 pub(crate) source: SubnetRegistryQuerySource,
24 pub entries: Vec<RegistryEntry>,
25}
26
27#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32pub(crate) enum SubnetRegistryQuerySource {
33 IcpCli,
34 LocalReplica,
35}
36
37#[derive(Debug)]
42pub enum SubnetRegistryQueryError {
43 Icp(IcpCommandError),
44 Registry(RegistryParseError),
45 Replica(ReplicaQueryError),
46}
47
48impl fmt::Display for SubnetRegistryQueryError {
49 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 Self::Icp(err) => write!(formatter, "{err}"),
52 Self::Registry(err) => write!(formatter, "{err}"),
53 Self::Replica(err) => write!(formatter, "{err}"),
54 }
55 }
56}
57
58impl Error for SubnetRegistryQueryError {
59 fn source(&self) -> Option<&(dyn Error + 'static)> {
60 match self {
61 Self::Icp(err) => Some(err),
62 Self::Registry(err) => Some(err),
63 Self::Replica(err) => Some(err),
64 }
65 }
66}
67
68impl From<IcpCommandError> for SubnetRegistryQueryError {
69 fn from(err: IcpCommandError) -> Self {
70 Self::Icp(err)
71 }
72}
73
74impl From<RegistryParseError> for SubnetRegistryQueryError {
75 fn from(err: RegistryParseError) -> Self {
76 Self::Registry(err)
77 }
78}
79
80impl From<ReplicaQueryError> for SubnetRegistryQueryError {
81 fn from(err: ReplicaQueryError) -> Self {
82 Self::Replica(err)
83 }
84}
85
86pub fn query_subnet_registry(
88 icp: &IcpCli,
89 root: &str,
90 network: &str,
91 icp_root: Option<&Path>,
92 candid_path: Option<&Path>,
93) -> Result<SubnetRegistryQuery, SubnetRegistryQueryError> {
94 if replica_query::should_use_local_replica_query(Some(network)) {
95 return query_local_subnet_registry(root, network, icp_root);
96 }
97
98 let output = icp.canister_query_output_with_candid(
99 root,
100 CANIC_SUBNET_REGISTRY_METHOD,
101 Some(ICP_JSON_OUTPUT),
102 candid_path,
103 )?;
104 Ok(SubnetRegistryQuery {
105 source: SubnetRegistryQuerySource::IcpCli,
106 entries: parse_registry_entries(&output)?,
107 })
108}
109
110fn query_local_subnet_registry(
111 root: &str,
112 network: &str,
113 icp_root: Option<&Path>,
114) -> Result<SubnetRegistryQuery, SubnetRegistryQueryError> {
115 let entries = icp_root.map_or_else(
116 || replica_query::query_subnet_registry_entries(Some(network), root),
117 |root_path| {
118 replica_query::query_subnet_registry_entries_from_root(Some(network), root, root_path)
119 },
120 )?;
121 Ok(SubnetRegistryQuery {
122 source: SubnetRegistryQuerySource::LocalReplica,
123 entries,
124 })
125}