cml/types/
child.rs

1// Copyright 2025 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;
6use crate::types::common::*;
7use crate::types::environment::EnvironmentRef;
8pub use cm_types::{Name, OnTerminate, StartupMode, Url};
9use json_spanned_value::Spanned;
10use reference_doc::ReferenceDoc;
11use serde::{Deserialize, Serialize};
12use std::path::PathBuf;
13use std::sync::Arc;
14
15/// Example:
16///
17/// ```json5
18/// children: [
19///     {
20///         name: "logger",
21///         url: "fuchsia-pkg://fuchsia.com/logger#logger.cm",
22///     },
23///     {
24///         name: "pkg_cache",
25///         url: "fuchsia-pkg://fuchsia.com/pkg_cache#meta/pkg_cache.cm",
26///         startup: "eager",
27///     },
28///     {
29///         name: "child",
30///         url: "#meta/child.cm",
31///     }
32/// ],
33/// ```
34///
35/// [component-url]: /docs/reference/components/url.md
36/// [doc-eager]: /docs/development/components/connect.md#eager
37/// [doc-reboot-on-terminate]: /docs/development/components/connect.md#reboot-on-terminate
38#[derive(ReferenceDoc, Deserialize, Debug, PartialEq, Serialize)]
39#[serde(deny_unknown_fields)]
40#[reference_doc(fields_as = "list", top_level_doc_after_fields)]
41pub struct Child {
42    /// The name of the child component instance, which is a string of one
43    /// or more of the following characters: `a-z`, `0-9`, `_`, `.`, `-`. The name
44    /// identifies this component when used in a [reference](#references).
45    pub name: Name,
46
47    /// The [component URL][component-url] for the child component instance.
48    pub url: Url,
49
50    /// The component instance's startup mode. One of:
51    /// - `lazy` _(default)_: Start the component instance only if another
52    ///     component instance binds to it.
53    /// - [`eager`][doc-eager]: Start the component instance as soon as its parent
54    ///     starts.
55    #[serde(default)]
56    #[serde(skip_serializing_if = "StartupMode::is_lazy")]
57    pub startup: StartupMode,
58
59    /// Determines the fault recovery policy to apply if this component terminates.
60    /// - `none` _(default)_: Do nothing.
61    /// - `reboot`: Gracefully reboot the system if the component terminates for
62    ///     any reason other than graceful exit. This is a special feature for use only by a narrow
63    ///     set of components; see [Termination policies][doc-reboot-on-terminate] for more
64    ///     information.
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub on_terminate: Option<OnTerminate>,
67
68    /// If present, the name of the environment to be assigned to the child component instance, one
69    /// of [`environments`](#environments). If omitted, the child will inherit the same environment
70    /// assigned to this component.
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub environment: Option<EnvironmentRef>,
73}
74
75#[derive(Deserialize, Debug, PartialEq, Clone)]
76#[serde(deny_unknown_fields)]
77pub struct ParsedChild {
78    pub name: Spanned<Name>,
79    pub url: Spanned<Url>,
80    pub startup: Option<Spanned<StartupMode>>,
81    pub on_terminate: Option<Spanned<OnTerminate>>,
82    pub environment: Option<Spanned<EnvironmentRef>>,
83}
84
85#[derive(Debug, Clone)]
86pub struct ContextChild {
87    pub name: ContextSpanned<Name>,
88    pub url: ContextSpanned<Url>,
89    pub startup: Option<ContextSpanned<StartupMode>>,
90    pub on_terminate: Option<ContextSpanned<OnTerminate>>,
91    pub environment: Option<ContextSpanned<EnvironmentRef>>,
92}
93
94impl PartialEq for ContextChild {
95    fn eq(&self, other: &Self) -> bool {
96        self.name.value == other.name.value
97    }
98}
99impl Eq for ContextChild {}
100
101impl Hydrate for ParsedChild {
102    type Output = ContextChild;
103
104    fn hydrate(self, file: &Arc<PathBuf>, buffer: &String) -> Result<Self::Output, Error> {
105        Ok(ContextChild {
106            name: hydrate_simple(self.name, file, buffer),
107            url: hydrate_simple(self.url, file, buffer),
108            startup: hydrate_opt_simple(self.startup, file, buffer),
109            on_terminate: hydrate_opt_simple(self.on_terminate, file, buffer),
110            environment: hydrate_opt_simple(self.environment, file, buffer),
111        })
112    }
113}