moniker/
extended_moniker.rs1use crate::error::MonikerError;
6use crate::moniker::Moniker;
7use cm_rust::{FidlIntoNative, NativeIntoFidl};
8use core::cmp::Ord;
9use std::fmt;
10
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
18#[derive(Eq, Ord, PartialOrd, PartialEq, Debug, Clone, Hash)]
19pub enum ExtendedMoniker {
20 ComponentInstance(Moniker),
21 ComponentManager,
22}
23
24pub const EXTENDED_MONIKER_COMPONENT_MANAGER_STR: &'static str = "<component_manager>";
26
27impl ExtendedMoniker {
28 pub fn unwrap_instance_moniker_or<E: std::error::Error>(
29 &self,
30 error: E,
31 ) -> Result<&Moniker, E> {
32 match self {
33 Self::ComponentManager => Err(error),
34 Self::ComponentInstance(moniker) => Ok(moniker),
35 }
36 }
37
38 pub fn has_prefix(&self, other: &Self) -> bool {
39 match (self, other) {
40 (_, Self::ComponentManager) => true,
41 (Self::ComponentManager, Self::ComponentInstance(_)) => false,
42 (Self::ComponentInstance(a), Self::ComponentInstance(b)) => a.has_prefix(b),
43 }
44 }
45
46 pub fn parse_str(rep: &str) -> Result<Self, MonikerError> {
47 if rep == EXTENDED_MONIKER_COMPONENT_MANAGER_STR {
48 Ok(ExtendedMoniker::ComponentManager)
49 } else {
50 Ok(ExtendedMoniker::ComponentInstance(Moniker::parse_str(rep)?))
51 }
52 }
53}
54
55impl TryFrom<&str> for ExtendedMoniker {
56 type Error = MonikerError;
57
58 fn try_from(input: &str) -> Result<Self, MonikerError> {
59 Self::parse_str(input)
60 }
61}
62
63impl std::str::FromStr for ExtendedMoniker {
64 type Err = MonikerError;
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 Self::parse_str(s)
67 }
68}
69
70impl fmt::Display for ExtendedMoniker {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 match self {
73 Self::ComponentInstance(m) => {
74 write!(f, "{}", m)?;
75 }
76 Self::ComponentManager => {
77 write!(f, "{}", EXTENDED_MONIKER_COMPONENT_MANAGER_STR)?;
78 }
79 }
80 Ok(())
81 }
82}
83
84impl AsRef<str> for ExtendedMoniker {
85 fn as_ref(&self) -> &str {
86 match self {
87 Self::ComponentInstance(m) => m.as_ref(),
88 Self::ComponentManager => EXTENDED_MONIKER_COMPONENT_MANAGER_STR,
89 }
90 }
91}
92
93impl From<Moniker> for ExtendedMoniker {
94 fn from(m: Moniker) -> Self {
95 Self::ComponentInstance(m)
96 }
97}
98
99impl FidlIntoNative<ExtendedMoniker> for String {
100 fn fidl_into_native(self) -> ExtendedMoniker {
101 self.parse().unwrap()
102 }
103}
104
105impl NativeIntoFidl<String> for ExtendedMoniker {
106 fn native_into_fidl(self) -> String {
107 self.to_string()
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn parse() {
117 assert_eq!(
118 ExtendedMoniker::parse_str(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap(),
119 ExtendedMoniker::ComponentManager
120 );
121 assert_eq!(
122 ExtendedMoniker::parse_str("/foo/bar").unwrap(),
123 ExtendedMoniker::ComponentInstance(Moniker::parse_str("/foo/bar").unwrap())
124 );
125 assert!(ExtendedMoniker::parse_str("").is_err(), "cannot be empty");
126 }
127
128 #[test]
129 fn has_prefix() {
130 let cm = ExtendedMoniker::ComponentManager;
131 let root = ExtendedMoniker::ComponentInstance(Moniker::root());
132 let a = ExtendedMoniker::ComponentInstance(Moniker::parse_str("a").unwrap());
133 let ab = ExtendedMoniker::ComponentInstance(Moniker::parse_str("a/b").unwrap());
134
135 assert!(cm.has_prefix(&cm));
136 assert!(!cm.has_prefix(&root));
137 assert!(!cm.has_prefix(&a));
138 assert!(!cm.has_prefix(&ab));
139
140 assert!(root.has_prefix(&cm));
141 assert!(root.has_prefix(&root));
142 assert!(!root.has_prefix(&a));
143 assert!(!root.has_prefix(&ab));
144
145 assert!(a.has_prefix(&cm));
146 assert!(a.has_prefix(&root));
147 assert!(a.has_prefix(&a));
148 assert!(!a.has_prefix(&ab));
149
150 assert!(ab.has_prefix(&cm));
151 assert!(ab.has_prefix(&root));
152 assert!(ab.has_prefix(&a));
153 assert!(ab.has_prefix(&ab));
154 }
155
156 #[test]
157 fn to_string_functions() {
158 let cm_moniker =
159 ExtendedMoniker::parse_str(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap();
160 let foobar_moniker = ExtendedMoniker::parse_str("foo/bar").unwrap();
161 let empty_moniker = ExtendedMoniker::parse_str(".").unwrap();
162
163 assert_eq!(format!("{}", cm_moniker), EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string());
164 assert_eq!(cm_moniker.to_string(), EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string());
165 assert_eq!(format!("{}", foobar_moniker), "foo/bar".to_string());
166 assert_eq!(foobar_moniker.to_string(), "foo/bar".to_string());
167 assert_eq!(format!("{}", empty_moniker), ".".to_string());
168 assert_eq!(empty_moniker.to_string(), ".".to_string());
169 }
170}