cordis_include/options.rs
1//! Serializable entry description — the on-disk shape of one plugin entry.
2
3use crate::node::Node;
4use serde::{Deserialize, Serialize};
5
6/// Whether a boolean is `false` (used by `skip_serializing_if`).
7fn is_false(value: &bool) -> bool {
8 !*value
9}
10
11/// One entry in a config file: a plugin instance plus its group position.
12///
13/// The declared field order is the serialization order (`id` and `name`
14/// first, `config` last), keeping files readable and diff-stable. Entries
15/// with a `group` array are groups; the array order is the child order.
16///
17/// `config` is stored raw: `${{ env.NAME }}` templates stay intact in the
18/// entry tree and are only expanded when the config is handed to a plugin
19/// (see [`crate::Entry::resolved_config`]).
20#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
21pub struct EntryOptions {
22 /// Stable identity of the entry. Missing ids are filled with a random
23 /// 6-character base36 id when the entry enters a tree and persisted on
24 /// the next write-back.
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub id: Option<String>,
27 /// Plugin name used to resolve the plugin implementation.
28 #[serde(default)]
29 pub name: String,
30 /// Whether the entry (and transitively its subtree) is disabled.
31 #[serde(default, skip_serializing_if = "is_false")]
32 pub disabled: bool,
33 /// Names of services that must be active before this entry starts.
34 #[serde(default, skip_serializing_if = "Vec::is_empty")]
35 pub inject: Vec<String>,
36 /// Child entries, in order. Non-empty only for group entries.
37 #[serde(default, skip_serializing_if = "Vec::is_empty")]
38 pub group: Vec<EntryOptions>,
39 /// Raw plugin configuration (templates unexpanded).
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub config: Option<Node>,
42}
43
44impl EntryOptions {
45 /// Create options for a plugin with the given name.
46 pub fn new(name: impl Into<String>) -> Self {
47 Self {
48 name: name.into(),
49 ..Self::default()
50 }
51 }
52
53 /// Set the explicit entry id.
54 pub fn with_id(mut self, id: impl Into<String>) -> Self {
55 self.id = Some(id.into());
56 self
57 }
58
59 /// Set the raw plugin configuration.
60 pub fn with_config(mut self, config: Node) -> Self {
61 self.config = Some(config);
62 self
63 }
64
65 /// Set the child entries (turning this entry into a group).
66 pub fn with_group(mut self, group: Vec<EntryOptions>) -> Self {
67 self.group = group;
68 self
69 }
70
71 /// Mark the entry (and its subtree) as disabled.
72 pub fn with_disabled(mut self, disabled: bool) -> Self {
73 self.disabled = disabled;
74 self
75 }
76
77 /// Declare services that must be active before this entry starts.
78 pub fn with_inject<I, S>(mut self, inject: I) -> Self
79 where
80 I: IntoIterator<Item = S>,
81 S: Into<String>,
82 {
83 self.inject = inject.into_iter().map(Into::into).collect();
84 self
85 }
86}