Skip to main content

moniker/
extended_moniker.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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/// One of:
15/// - A moniker
16/// - A marker representing component manager's realm
17#[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
24/// The string representation of ExtendedMoniker::ComponentManager
25pub 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    pub fn as_str(&self) -> &str {
55        match self {
56            Self::ComponentInstance(m) => m.as_str(),
57            Self::ComponentManager => EXTENDED_MONIKER_COMPONENT_MANAGER_STR,
58        }
59    }
60}
61
62impl TryFrom<&str> for ExtendedMoniker {
63    type Error = MonikerError;
64
65    fn try_from(input: &str) -> Result<Self, MonikerError> {
66        Self::parse_str(input)
67    }
68}
69
70impl std::str::FromStr for ExtendedMoniker {
71    type Err = MonikerError;
72    fn from_str(s: &str) -> Result<Self, Self::Err> {
73        Self::parse_str(s)
74    }
75}
76
77impl fmt::Display for ExtendedMoniker {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            Self::ComponentInstance(m) => {
81                write!(f, "{}", m)?;
82            }
83            Self::ComponentManager => {
84                write!(f, "{}", EXTENDED_MONIKER_COMPONENT_MANAGER_STR)?;
85            }
86        }
87        Ok(())
88    }
89}
90
91impl AsRef<str> for ExtendedMoniker {
92    fn as_ref(&self) -> &str {
93        match self {
94            Self::ComponentInstance(m) => m.as_ref(),
95            Self::ComponentManager => EXTENDED_MONIKER_COMPONENT_MANAGER_STR,
96        }
97    }
98}
99
100impl From<Moniker> for ExtendedMoniker {
101    fn from(m: Moniker) -> Self {
102        Self::ComponentInstance(m)
103    }
104}
105
106impl FidlIntoNative<ExtendedMoniker> for String {
107    fn fidl_into_native(self) -> ExtendedMoniker {
108        self.parse().unwrap()
109    }
110}
111
112impl NativeIntoFidl<String> for ExtendedMoniker {
113    fn native_into_fidl(self) -> String {
114        self.to_string()
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn parse() {
124        assert_eq!(
125            ExtendedMoniker::parse_str(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap(),
126            ExtendedMoniker::ComponentManager
127        );
128        assert_eq!(
129            ExtendedMoniker::parse_str("/foo/bar").unwrap(),
130            ExtendedMoniker::ComponentInstance(Moniker::parse_str("/foo/bar").unwrap())
131        );
132        assert!(ExtendedMoniker::parse_str("").is_err(), "cannot be empty");
133    }
134
135    #[test]
136    fn has_prefix() {
137        let cm = ExtendedMoniker::ComponentManager;
138        let root = ExtendedMoniker::ComponentInstance(Moniker::root());
139        let a = ExtendedMoniker::ComponentInstance(Moniker::parse_str("a").unwrap());
140        let ab = ExtendedMoniker::ComponentInstance(Moniker::parse_str("a/b").unwrap());
141
142        assert!(cm.has_prefix(&cm));
143        assert!(!cm.has_prefix(&root));
144        assert!(!cm.has_prefix(&a));
145        assert!(!cm.has_prefix(&ab));
146
147        assert!(root.has_prefix(&cm));
148        assert!(root.has_prefix(&root));
149        assert!(!root.has_prefix(&a));
150        assert!(!root.has_prefix(&ab));
151
152        assert!(a.has_prefix(&cm));
153        assert!(a.has_prefix(&root));
154        assert!(a.has_prefix(&a));
155        assert!(!a.has_prefix(&ab));
156
157        assert!(ab.has_prefix(&cm));
158        assert!(ab.has_prefix(&root));
159        assert!(ab.has_prefix(&a));
160        assert!(ab.has_prefix(&ab));
161    }
162
163    #[test]
164    fn to_string_functions() {
165        let cm_moniker =
166            ExtendedMoniker::parse_str(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap();
167        let foobar_moniker = ExtendedMoniker::parse_str("foo/bar").unwrap();
168        let empty_moniker = ExtendedMoniker::parse_str(".").unwrap();
169
170        assert_eq!(format!("{}", cm_moniker), EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string());
171        assert_eq!(cm_moniker.to_string(), EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string());
172        assert_eq!(format!("{}", foobar_moniker), "foo/bar".to_string());
173        assert_eq!(foobar_moniker.to_string(), "foo/bar".to_string());
174        assert_eq!(format!("{}", empty_moniker), ".".to_string());
175        assert_eq!(empty_moniker.to_string(), ".".to_string());
176    }
177}