use super::ReplicaQueryError;
use candid::{CandidType, Decode, Principal};
use canic_core::dto::{error::Error as CanicDtoError, state::BootstrapStatusResponse};
use serde::Deserialize;
use std::fmt;
pub(super) fn decode_bootstrap_status_response(
bytes: &[u8],
) -> Result<BootstrapStatusResponse, ReplicaQueryError> {
Decode!(bytes, BootstrapStatusResponse).map_err(|err| ReplicaQueryError::Query(err.to_string()))
}
pub(super) fn decode_cycle_balance_response(bytes: &[u8]) -> Result<u128, ReplicaQueryError> {
let result = Decode!(bytes, Result<u128, CanicDtoError>)
.map_err(|err| ReplicaQueryError::Query(err.to_string()))?;
result.map_err(|err| ReplicaQueryError::Query(err.to_string()))
}
pub(super) fn decode_subnet_registry_response(
bytes: &[u8],
) -> Result<SubnetRegistryResponseWire, ReplicaQueryError> {
let result = Decode!(&bytes, Result<SubnetRegistryResponseWire, CanicErrorWire>)
.map_err(|err| ReplicaQueryError::Query(err.to_string()))?;
result.map_err(|err| ReplicaQueryError::Query(err.to_string()))
}
#[derive(CandidType, Deserialize)]
pub(super) struct SubnetRegistryResponseWire(pub(super) Vec<SubnetRegistryEntryWire>);
impl SubnetRegistryResponseWire {
pub(super) fn roles(&self) -> Vec<String> {
self.0.iter().map(|entry| entry.role.clone()).collect()
}
pub(super) fn to_cli_json(&self) -> serde_json::Value {
serde_json::json!({
"Ok": self.0.iter().map(SubnetRegistryEntryWire::to_cli_json).collect::<Vec<_>>()
})
}
}
#[derive(CandidType, Deserialize)]
pub(super) struct SubnetRegistryEntryWire {
pub(super) pid: Principal,
pub(super) role: String,
pub(super) record: CanisterInfoWire,
}
impl SubnetRegistryEntryWire {
fn to_cli_json(&self) -> serde_json::Value {
serde_json::json!({
"pid": self.pid.to_text(),
"role": self.role,
"record": self.record.to_cli_json(),
})
}
}
#[derive(CandidType, Deserialize)]
pub(super) struct CanisterInfoWire {
pub(super) pid: Principal,
pub(super) role: String,
pub(super) parent_pid: Option<Principal>,
pub(super) module_hash: Option<Vec<u8>>,
pub(super) created_at: u64,
}
impl CanisterInfoWire {
fn to_cli_json(&self) -> serde_json::Value {
serde_json::json!({
"pid": self.pid.to_text(),
"role": self.role,
"parent_pid": self.parent_pid.as_ref().map(Principal::to_text),
"module_hash": self.module_hash,
"created_at": self.created_at.to_string(),
})
}
}
#[derive(CandidType, Deserialize)]
pub(super) struct CanicErrorWire {
code: ErrorCodeWire,
message: String,
}
impl fmt::Display for CanicErrorWire {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{:?}: {}", self.code, self.message)
}
}
#[derive(CandidType, Debug, Deserialize)]
enum ErrorCodeWire {
Conflict,
Forbidden,
Internal,
InvalidInput,
InvariantViolation,
NotFound,
PolicyInstanceRequiresSingletonWithDirectory,
PolicyReplicaRequiresSingletonWithScaling,
PolicyRoleAlreadyRegistered,
PolicyShardRequiresSingletonWithSharding,
PolicySingletonAlreadyRegisteredUnderParent,
ResourceExhausted,
Unauthorized,
Unavailable,
}
#[cfg(test)]
mod tests;