Parse a simple label selector string into key-value pairs. Format: "key1=value1,key2=value2" Returns a `HashMap` of label requirements. Note: Input validation should be performed at the gRPC layer using `grpc::validation::validate_label_selector()` before calling this function. Errors returned here indicate unexpected internal errors, not user input errors.
(selector: &str)
| 552 | /// `grpc::validation::validate_label_selector()` before calling this function. |
| 553 | /// Errors returned here indicate unexpected internal errors, not user input errors. |
| 554 | pub fn parse_label_selector(selector: &str) -> PersistenceResult<HashMap<String, String>> { |
| 555 | if selector.is_empty() { |
| 556 | return Ok(HashMap::new()); |
| 557 | } |
| 558 | |
| 559 | let mut labels = HashMap::new(); |
| 560 | for pair in selector.split(',') { |
| 561 | let pair = pair.trim(); |
| 562 | if pair.is_empty() { |
| 563 | continue; |
| 564 | } |
| 565 | |
| 566 | let parts: Vec<&str> = pair.splitn(2, '=').collect(); |
| 567 | if parts.len() != 2 { |
| 568 | return Err(PersistenceError::Decode(format!( |
| 569 | "invalid label selector: expected 'key=value', got '{pair}'" |
| 570 | ))); |
| 571 | } |
| 572 | |
| 573 | let key = parts[0].trim(); |
| 574 | let value = parts[1].trim(); |
| 575 | |
| 576 | if key.is_empty() { |
| 577 | return Err(PersistenceError::Decode(format!( |
| 578 | "invalid label selector: key cannot be empty in '{pair}'" |
| 579 | ))); |
| 580 | } |
| 581 | |
| 582 | labels.insert(key.to_string(), value.to_string()); |
| 583 | } |
| 584 | |
| 585 | Ok(labels) |
| 586 | } |
| 587 | |
| 588 | /// Unconditional write helpers — test-only. |
| 589 | /// |