seda_sdk_rs/process.rs
1//! Process management utilities for the SDK.
2//!
3//! This module provides functionality for handling program arguments, environment variables,
4//! and process termination with specific exit codes and results.
5//!
6//! # Examples
7//!
8//! ```no_run
9//! use seda_sdk_rs::process::Process;
10//!
11//! // Handle success case
12//! let result = vec![1, 2, 3];
13//! Process::success(&result);
14//!
15//! // Handle error case with message
16//! Process::exit_with_message(1, "Operation failed");
17//! ```
18
19use std::{
20 collections::BTreeMap,
21 env::{self},
22 process,
23};
24
25use crate::{
26 raw::{self},
27 vm_modes::{DR_REPLICATION_FACTOR_ENV_KEY, VM_MODE_DR, VM_MODE_ENV_KEY, VM_MODE_TALLY},
28};
29
30/// Utilities for managing process-level operations.
31pub struct Process;
32
33impl Process {
34 /// Returns a vector of command-line arguments passed to the program.
35 ///
36 /// # Examples
37 ///
38 /// ```
39 /// use seda_sdk_rs::process::Process;
40 ///
41 /// let args = Process::args();
42 /// // args[0] is the program name
43 /// // args[1] would be the first argument
44 /// ```
45 pub fn args() -> Vec<String> {
46 env::args().collect()
47 }
48
49 /// Returns a map of all environment variables.
50 ///
51 /// # Examples
52 ///
53 /// ```
54 /// use seda_sdk_rs::process::Process;
55 ///
56 /// std::env::set_var("TEST_VAR", "test_value");
57 ///
58 /// let env_vars = Process::envs();
59 /// assert!(env_vars.contains_key("TEST_VAR"));
60 /// for (key, value) in env_vars {
61 /// println!("{}: {}", key, value);
62 /// }
63 /// ```
64 pub fn envs() -> BTreeMap<String, String> {
65 env::vars().collect()
66 }
67
68 /// Retrieves and decodes the data request inputs
69 ///
70 /// # Panics
71 ///
72 /// This function will panic if:
73 /// - There were no arguments passed to the program.
74 /// - The second argument (index 1) is not a valid hex string.
75 ///
76 /// # Examples
77 ///
78 /// ```no_run
79 /// use seda_sdk_rs::process::Process;
80 ///
81 /// let input_bytes = Process::get_inputs();
82 /// // Process the input bytes...
83 /// ```
84 pub fn get_inputs() -> Vec<u8> {
85 // 1 is inputs because 0 is name of the program
86 let args = Self::args();
87 let raw_input = args.get(1).expect("Arg at index 1 must best set");
88
89 hex::decode(raw_input).expect("Arg at index 1 is not a valid hex string")
90 }
91
92 /// Gets the VM mode from environment variables.
93 ///
94 /// # Panics
95 ///
96 /// This function will panic if the `VM_MODE` environment variable is not set.
97 /// Which should never happen in a properly configured environment.
98 fn get_vm_mode() -> String {
99 env::var(VM_MODE_ENV_KEY).expect("VM_MODE is not set in environment")
100 }
101
102 /// Checks if the current VM mode is set to tally mode.
103 ///
104 /// # Examples
105 ///
106 /// ```
107 /// use seda_sdk_rs::process::Process;
108 ///
109 /// std::env::set_var("VM_MODE", "tally");
110 /// if Process::is_tally_vm_mode() {
111 /// // Handle tally mode specific logic
112 /// }
113 /// ```
114 pub fn is_tally_vm_mode() -> bool {
115 Self::get_vm_mode() == VM_MODE_TALLY
116 }
117
118 /// Checks if the current VM mode is set to DR mode.
119 ///
120 /// # Examples
121 ///
122 /// ```no_run
123 /// use seda_sdk_rs::process::Process;
124 ///
125 /// if Process::is_dr_vm_mode() {
126 /// let replication = Process::replication_factor();
127 /// // Handle DR mode specific logic
128 /// }
129 /// ```
130 pub fn is_dr_vm_mode() -> bool {
131 Self::get_vm_mode() == VM_MODE_DR
132 }
133
134 /// Exits the process successfully (code 0) with the given result.
135 ///
136 /// # Examples
137 ///
138 /// ```no_run
139 /// use seda_sdk_rs::process::Process;
140 ///
141 /// let result = vec![0x01, 0x02, 0x03];
142 /// Process::success(&result);
143 /// ```
144 pub fn success(result: &[u8]) -> ! {
145 Self::exit_with_result(0, result);
146 }
147
148 /// Exits the process with an error (code 1) and the given result.
149 ///
150 /// # Examples
151 ///
152 /// ```no_run
153 /// use seda_sdk_rs::process::Process;
154 ///
155 /// let error_data = vec![0xFF];
156 /// Process::error(&error_data);
157 /// ```
158 pub fn error(result: &[u8]) -> ! {
159 Self::exit_with_result(1, result);
160 }
161
162 /// Gets the replication factor for the data request
163 ///
164 /// # Panics
165 ///
166 /// This function will panic if:
167 /// - The `DR_REPLICATION_FACTOR_ENV_KEY` environment variable is not set.
168 /// - The value of `DR_REPLICATION_FACTOR_ENV_KEY` is not a valid `u16`.
169 ///
170 /// These conditions should never happen in a properly configured environment.
171 ///
172 /// # Examples
173 ///
174 /// ```no_run
175 /// use seda_sdk_rs::process::Process;
176 ///
177 /// if Process::is_dr_vm_mode() {
178 /// let factor = Process::replication_factor();
179 /// println!("Replication factor: {}", factor);
180 /// }
181 /// ```
182 pub fn replication_factor() -> u16 {
183 let variable = env::var(DR_REPLICATION_FACTOR_ENV_KEY)
184 .unwrap_or_else(|_| panic!("{DR_REPLICATION_FACTOR_ENV_KEY} is not set in environment"));
185
186 variable
187 .parse()
188 .unwrap_or_else(|_| panic!("{DR_REPLICATION_FACTOR_ENV_KEY} must be a valid u16"))
189 }
190
191 /// Exits the process with the given code and message.
192 ///
193 /// # Examples
194 ///
195 /// ```no_run
196 /// use seda_sdk_rs::process::Process;
197 ///
198 /// // Exit with an error message
199 /// Process::exit_with_message(1, "Operation failed: invalid input");
200 ///
201 /// // Exit with success message
202 /// Process::exit_with_message(0, "Operation completed successfully");
203 /// ```
204 pub fn exit_with_message(code: u8, message: &str) -> ! {
205 let message_encoded = message.as_bytes();
206 Self::exit_with_result(code, message_encoded);
207 }
208
209 /// Exits the process with the given code and result bytes.
210 ///
211 /// # Examples
212 ///
213 /// ```no_run
214 /// use seda_sdk_rs::process::Process;
215 ///
216 /// let result = vec![1, 2, 3, 4];
217 /// Process::exit_with_result(0, &result);
218 /// ```
219 pub fn exit_with_result(code: u8, result: &[u8]) -> ! {
220 unsafe { raw::execution_result(result.as_ptr(), result.len() as u32) };
221 process::exit(code.into());
222 }
223
224 /// Exits the process with the given code and an empty result.
225 ///
226 /// # Examples
227 ///
228 /// ```no_run
229 /// use seda_sdk_rs::process::Process;
230 ///
231 /// // Exit successfully with no result
232 /// Process::exit(0);
233 ///
234 /// // Exit with error code
235 /// Process::exit(1);
236 /// ```
237 pub fn exit(code: u8) -> ! {
238 Self::exit_with_result(code, &[]);
239 }
240}