1#![deny(missing_docs)]
2#![deny(unreachable_pub, rust_2018_idioms)]
3#![forbid(unsafe_code)]
4
5pub mod config {
12 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
14 pub enum Environment {
15 Dev,
17 Staging,
19 Prod,
21 }
22
23 impl Environment {
24 pub fn parse(s: &str) -> Option<Self> {
26 match s {
27 "dev" => Some(Self::Dev),
28 "staging" => Some(Self::Staging),
29 "prod" => Some(Self::Prod),
30 _ => None,
31 }
32 }
33
34 pub const fn as_str(&self) -> &'static str {
36 match self {
37 Environment::Dev => "dev",
38 Environment::Staging => "staging",
39 Environment::Prod => "prod",
40 }
41 }
42 }
43}
44
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub enum Product {
48 Runtime,
50 Edgeplane,
52 Actiongraph,
54 Dataguard,
56}
57
58impl Product {
59 pub const fn id(&self) -> &'static str {
61 match self {
62 Product::Runtime => "runtime",
63 Product::Edgeplane => "edgeplane",
64 Product::Actiongraph => "actiongraph",
65 Product::Dataguard => "dataguard",
66 }
67 }
68}
69
70pub mod paths {
72 use super::Product;
73 use std::path::{Path, PathBuf};
74
75 pub const ENV_SHM_PARENT: &str = "SHM_PARENT";
77 pub const ENV_LANE_PATH: &str = "BYTEOR_LANE_PATH";
79 pub const ENV_SPEC: &str = "BYTEOR_SPEC";
81 pub const ENV_WAIT: &str = "BYTEOR_WAIT";
83
84 pub const DEFAULT_SHM_PARENT: &str = "/dev/shm";
86 pub const DEFAULT_RUN_DIR: &str = "/run/byteor";
88 pub const DEFAULT_SPEC_PATH: &str = "/etc/byteor/spec.kv";
90
91 pub fn shm_parent_from_env() -> PathBuf {
93 std::env::var(ENV_SHM_PARENT)
94 .ok()
95 .map(PathBuf::from)
96 .unwrap_or_else(|| PathBuf::from(DEFAULT_SHM_PARENT))
97 }
98
99 pub fn lane_path_from_env() -> Option<PathBuf> {
101 std::env::var(ENV_LANE_PATH).ok().map(PathBuf::from)
102 }
103
104 pub fn service_single_ring_lane_path(product: Product) -> PathBuf {
109 let run_dir = Path::new(DEFAULT_RUN_DIR);
110 match product {
111 Product::Runtime => run_dir.join("single_ring.shm"),
112 other => run_dir.join(format!("{}-single_ring.shm", other.id())),
113 }
114 }
115
116 fn try_prepare_run_dir() -> Option<PathBuf> {
117 let run_dir = PathBuf::from(DEFAULT_RUN_DIR);
118 if run_dir.exists() {
119 if run_dir.is_dir() {
120 return Some(run_dir);
121 }
122 return None;
123 }
124
125 if std::fs::create_dir_all(&run_dir).is_ok() {
126 Some(run_dir)
127 } else {
128 None
129 }
130 }
131
132 pub fn default_lane_path_for_run(
140 product: Product,
141 cli_lane_path: Option<PathBuf>,
142 shm_parent: &Path,
143 ) -> PathBuf {
144 if let Some(p) = cli_lane_path {
145 return p;
146 }
147 if let Some(p) = lane_path_from_env() {
148 return p;
149 }
150 if try_prepare_run_dir().is_some() {
151 return service_single_ring_lane_path(product);
152 }
153 shm_parent.join(format!(
154 "byteor-{}-single-ring-{}.shm",
155 product.id(),
156 std::process::id()
157 ))
158 }
159
160 #[cfg(test)]
161 mod tests {
162 use super::*;
163
164 #[test]
165 fn service_paths_are_deterministic_and_product_scoped() {
166 assert_eq!(
167 service_single_ring_lane_path(Product::Runtime),
168 PathBuf::from("/run/byteor/single_ring.shm")
169 );
170 assert_eq!(
171 service_single_ring_lane_path(Product::Edgeplane),
172 PathBuf::from("/run/byteor/edgeplane-single_ring.shm")
173 );
174 }
175 }
176}