| 433 | result: StateType, |
| 434 | } |
| 435 | pub fn parse_state_path(paths: &[IDLValue]) -> anyhow::Result<StatePath> { |
| 436 | let mut res = Vec::new(); |
| 437 | let mut prefix = String::new(); |
| 438 | let mut kind = StateKind::Canister; |
| 439 | let mut effective_id = None; |
| 440 | let mut result = StateType::Blob; |
| 441 | if paths.len() > 5 || paths.is_empty() { |
| 442 | return Err(anyhow!("state path can only be 1-5 segments")); |
| 443 | } |
| 444 | for (i, v) in paths.iter().enumerate() { |
| 445 | match v { |
| 446 | IDLValue::Text(t) => { |
| 447 | match i { |
| 448 | 0 => { |
| 449 | prefix.clone_from(t); |
| 450 | if prefix == "subnet" { |
| 451 | kind = StateKind::Subnet; |
| 452 | } |
| 453 | } |
| 454 | 1 => return Err(anyhow!("second path has to be a principal")), |
| 455 | 2 => { |
| 456 | result = match (prefix.as_str(), t.as_str()) { |
| 457 | ("canister", "controllers") => StateType::Controllers, |
| 458 | ( |
| 459 | "canister", |
| 460 | "metadata/candid:service" |
| 461 | | "metadata/candid:args" |
| 462 | | "metadata/motoko:stable-types", |
| 463 | ) => StateType::Text, |
| 464 | ("api_boundary_nodes", "domain" | "ipv4_address" | "ipv6_address") => { |
| 465 | StateType::Text |
| 466 | } |
| 467 | ("subnet", "canister_ranges") => StateType::Ranges, |
| 468 | ("subnet", "metrics") => StateType::Metrics, |
| 469 | ("subnet", "node") => { |
| 470 | // For some reason, /subnet/.../node is only available on canister read_state |
| 471 | effective_id = None; |
| 472 | kind = StateKind::Canister; |
| 473 | StateType::Subtree |
| 474 | } |
| 475 | _ => StateType::Blob, |
| 476 | }; |
| 477 | } |
| 478 | _ => (), |
| 479 | } |
| 480 | res.extend(t.split('/').map(|str| str.as_bytes().into())); |
| 481 | } |
| 482 | IDLValue::Principal(id) => { |
| 483 | match i { |
| 484 | 1 => effective_id = Some(*id), |
| 485 | 3 => result = StateType::Blob, |
| 486 | _ => return Err(anyhow!("{i}th path cannot be a principal")), |
| 487 | } |
| 488 | res.push(id.as_slice().into()) |
| 489 | } |
| 490 | _ => return Err(anyhow!("state path can only be either text or principal")), |
| 491 | } |
| 492 | } |