blob: 50da16ed7ebea857f9da8344838a2939cb46e7dc [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::{
abs_moniker::{AbsoluteMoniker, AbsoluteMonikerBase},
error::MonikerError,
},
core::cmp::Ord,
std::fmt,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// One of:
/// - An absolute moniker
/// - A marker representing component manager's realm
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Eq, Ord, PartialOrd, PartialEq, Debug, Clone, Hash)]
pub enum ExtendedMoniker {
ComponentInstance(AbsoluteMoniker),
ComponentManager,
}
/// The string representation of ExtendedMoniker::ComponentManager
const EXTENDED_MONIKER_COMPONENT_MANAGER_STR: &'static str = "<component_manager>";
impl ExtendedMoniker {
pub fn unwrap_instance_moniker_or<E: std::error::Error>(
&self,
error: E,
) -> Result<&AbsoluteMoniker, E> {
match self {
Self::ComponentManager => Err(error),
Self::ComponentInstance(moniker) => Ok(moniker),
}
}
pub fn contains_in_realm(&self, other: &ExtendedMoniker) -> bool {
match (self, other) {
(Self::ComponentManager, _) => true,
(Self::ComponentInstance(_), Self::ComponentManager) => false,
(Self::ComponentInstance(a), Self::ComponentInstance(b)) => a.contains_in_realm(b),
}
}
pub fn parse_str(rep: &str) -> Result<Self, MonikerError> {
if rep == EXTENDED_MONIKER_COMPONENT_MANAGER_STR {
Ok(ExtendedMoniker::ComponentManager)
} else {
Ok(ExtendedMoniker::ComponentInstance(AbsoluteMoniker::parse_str(rep)?))
}
}
}
impl fmt::Display for ExtendedMoniker {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ComponentInstance(m) => {
write!(f, "{}", m)?;
}
Self::ComponentManager => {
write!(f, "{}", EXTENDED_MONIKER_COMPONENT_MANAGER_STR)?;
}
}
Ok(())
}
}
impl From<AbsoluteMoniker> for ExtendedMoniker {
fn from(m: AbsoluteMoniker) -> Self {
Self::ComponentInstance(m)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn extended_monikers_parse() {
assert_eq!(
ExtendedMoniker::parse_str(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap(),
ExtendedMoniker::ComponentManager
);
assert_eq!(
ExtendedMoniker::parse_str("/foo/bar").unwrap(),
ExtendedMoniker::ComponentInstance(AbsoluteMoniker::parse_str("/foo/bar").unwrap())
);
assert!(ExtendedMoniker::parse_str("").is_err(), "cannot be empty");
assert!(ExtendedMoniker::parse_str("foo/bar").is_err(), "must start with /");
}
#[test]
fn to_string_functions() {
let cm_moniker =
ExtendedMoniker::parse_str(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap();
let foobar_moniker = ExtendedMoniker::parse_str("/foo/bar").unwrap();
let empty_moniker = ExtendedMoniker::parse_str("/").unwrap();
assert_eq!(format!("{}", cm_moniker), EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string());
assert_eq!(cm_moniker.to_string(), EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string());
assert_eq!(format!("{}", foobar_moniker), "/foo/bar".to_string());
assert_eq!(foobar_moniker.to_string(), "/foo/bar".to_string());
assert_eq!(format!("{}", empty_moniker), "/".to_string());
assert_eq!(empty_moniker.to_string(), "/".to_string());
}
}