1use crate::component_instance::{
6 ComponentInstanceInterface, ExtendedInstanceInterface, WeakExtendedInstanceInterface,
7};
8use crate::error::ComponentInstanceError;
9use cm_rust::{RegistrationDeclCommon, RegistrationSource, RunnerRegistration, SourceName};
10use cm_types::{Name, Url};
11use fidl_fuchsia_component_decl as fdecl;
12use std::collections::HashMap;
13use std::sync::Arc;
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug)]
19pub struct Environment<Component: ComponentInstanceInterface> {
20 name: Option<Name>,
23 parent: WeakExtendedInstanceInterface<Component>,
25 extends: EnvironmentExtends,
27 runner_registry: RunnerRegistry,
29 debug_registry: DebugRegistry,
31}
32
33impl<C: ComponentInstanceInterface> Environment<C> {
34 pub fn new(
35 name: Option<Name>,
36 parent: WeakExtendedInstanceInterface<C>,
37 extends: EnvironmentExtends,
38 runner_registry: RunnerRegistry,
39 debug_registry: DebugRegistry,
40 ) -> Self {
41 Self { name, parent, extends, runner_registry, debug_registry }
42 }
43
44 pub fn name(&self) -> Option<&Name> {
47 self.name.as_ref()
48 }
49
50 pub fn parent(&self) -> &WeakExtendedInstanceInterface<C> {
52 &self.parent
53 }
54
55 pub fn extends(&self) -> &EnvironmentExtends {
57 &self.extends
58 }
59
60 pub fn runner_registry(&self) -> &RunnerRegistry {
62 &self.runner_registry
63 }
64
65 pub fn debug_registry(&self) -> &DebugRegistry {
67 &self.debug_registry
68 }
69
70 pub fn get_registered_runner(
73 &self,
74 name: &Name,
75 ) -> Result<Option<(ExtendedInstanceInterface<C>, RunnerRegistration)>, ComponentInstanceError>
76 {
77 let parent = self.parent().upgrade()?;
78 match self.runner_registry().get_runner(name) {
79 Some(reg) => Ok(Some((parent, reg.clone()))),
80 None => match self.extends() {
81 EnvironmentExtends::Realm => match parent {
82 ExtendedInstanceInterface::<C>::Component(parent) => {
83 parent.environment().get_registered_runner(name)
84 }
85 ExtendedInstanceInterface::<C>::AboveRoot(_) => {
86 unreachable!("root env can't extend")
87 }
88 },
89 EnvironmentExtends::None => {
90 return Ok(None);
91 }
92 },
93 }
94 }
95
96 pub fn get_debug_capability(
100 &self,
101 name: &Name,
102 ) -> Result<
103 Option<(ExtendedInstanceInterface<C>, Option<Name>, DebugRegistration)>,
104 ComponentInstanceError,
105 > {
106 let parent = self.parent().upgrade()?;
107 match self.debug_registry().get_capability(name) {
108 Some(reg) => Ok(Some((parent, self.name().cloned(), reg.clone()))),
109 None => match self.extends() {
110 EnvironmentExtends::Realm => match parent {
111 ExtendedInstanceInterface::<C>::Component(parent) => {
112 parent.environment().get_debug_capability(name)
113 }
114 ExtendedInstanceInterface::<C>::AboveRoot(_) => {
115 unreachable!("root env can't extend")
116 }
117 },
118 EnvironmentExtends::None => {
119 return Ok(None);
120 }
121 },
122 }
123 }
124}
125
126#[derive(Debug, Clone, PartialEq)]
128pub enum EnvironmentExtends {
129 Realm,
131 None,
133}
134
135impl From<fdecl::EnvironmentExtends> for EnvironmentExtends {
136 fn from(e: fdecl::EnvironmentExtends) -> Self {
137 match e {
138 fdecl::EnvironmentExtends::Realm => Self::Realm,
139 fdecl::EnvironmentExtends::None => Self::None,
140 }
141 }
142}
143
144#[derive(Clone, Debug)]
148pub struct RunnerRegistry {
149 runners: HashMap<Name, RunnerRegistration>,
150}
151
152impl RunnerRegistry {
153 pub fn default() -> Self {
154 Self { runners: HashMap::new() }
155 }
156
157 pub fn new(runners: HashMap<Name, RunnerRegistration>) -> Self {
158 Self { runners }
159 }
160
161 pub fn from_decl(regs: &Vec<RunnerRegistration>) -> Self {
162 let mut runners = HashMap::new();
163 for reg in regs {
164 runners.insert(reg.target_name.clone(), reg.clone());
165 }
166 Self { runners }
167 }
168 pub fn get_runner(&self, name: &Name) -> Option<&RunnerRegistration> {
169 self.runners.get(name)
170 }
171}
172
173#[derive(Default, Debug, Clone, PartialEq, Eq)]
175pub struct DebugRegistry {
176 pub debug_capabilities: HashMap<Name, DebugRegistration>,
177}
178
179#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct DebugRegistration {
182 pub source: RegistrationSource,
183 pub source_name: Name,
184}
185
186impl SourceName for DebugRegistration {
187 fn source_name(&self) -> &Name {
188 &self.source_name
189 }
190}
191
192impl RegistrationDeclCommon for DebugRegistration {
193 const TYPE: &'static str = "protocol";
194
195 fn source(&self) -> &RegistrationSource {
196 &self.source
197 }
198}
199
200impl From<Vec<cm_rust::DebugRegistration>> for DebugRegistry {
201 fn from(regs: Vec<cm_rust::DebugRegistration>) -> Self {
202 let mut debug_capabilities = HashMap::new();
203 for reg in regs {
204 match reg {
205 cm_rust::DebugRegistration::Protocol(r) => {
206 debug_capabilities.insert(
207 r.target_name,
208 DebugRegistration { source_name: r.source_name, source: r.source },
209 );
210 }
211 };
212 }
213 Self { debug_capabilities }
214 }
215}
216
217impl DebugRegistry {
218 pub fn get_capability(&self, name: &Name) -> Option<&DebugRegistration> {
219 self.debug_capabilities.get(name)
220 }
221}
222
223pub fn find_first_absolute_ancestor_url<C: ComponentInstanceInterface>(
224 component: &Arc<C>,
225) -> Result<Url, ComponentInstanceError> {
226 let mut parent = component.try_get_parent()?;
227 loop {
228 match parent {
229 ExtendedInstanceInterface::Component(parent_component) => {
230 if !parent_component.url().is_relative() {
231 return Ok(parent_component.url().clone());
232 }
233 parent = parent_component.try_get_parent()?;
234 }
235 ExtendedInstanceInterface::AboveRoot(_) => {
236 return Err(ComponentInstanceError::NoAbsoluteUrl {
237 url: component.url().to_string(),
238 moniker: component.moniker().clone(),
239 });
240 }
241 }
242 }
243}