shape_runtime/stdlib/
env.rs1use crate::marshal::{register_typed_fn_0, register_typed_fn_1};
22use crate::module_exports::ModuleExports;
23use crate::typed_module_exports::{ConcreteReturn, ConcreteType, TypedReturn};
24use std::sync::Arc;
25
26pub fn create_env_module() -> ModuleExports {
28 let mut module = ModuleExports::new("std::core::env");
29 module.description = "Environment variables and system information".to_string();
30
31 register_typed_fn_1::<_, Arc<String>>(
33 &mut module,
34 "has",
35 "Check if an environment variable is set",
36 "name",
37 "string",
38 ConcreteType::Bool,
39 |name, ctx| {
40 crate::module_exports::check_permission(ctx, shape_abi_v1::Permission::Env)?;
41 Ok(TypedReturn::Concrete(ConcreteReturn::Bool(
42 std::env::var(name.as_str()).is_ok(),
43 )))
44 },
45 );
46
47 register_typed_fn_0(
49 &mut module,
50 "cwd",
51 "Get the current working directory",
52 ConcreteType::String,
53 |ctx| {
54 crate::module_exports::check_permission(ctx, shape_abi_v1::Permission::Env)?;
55 let cwd = std::env::current_dir().map_err(|e| format!("env.cwd() failed: {}", e))?;
56 Ok(TypedReturn::Concrete(ConcreteReturn::String(
57 cwd.to_string_lossy().into_owned(),
58 )))
59 },
60 );
61
62 register_typed_fn_0(
64 &mut module,
65 "os",
66 "Get the operating system name (e.g. linux, macos, windows)",
67 ConcreteType::String,
68 |ctx| {
69 crate::module_exports::check_permission(ctx, shape_abi_v1::Permission::Env)?;
70 Ok(TypedReturn::Concrete(ConcreteReturn::String(
71 std::env::consts::OS.to_string(),
72 )))
73 },
74 );
75
76 register_typed_fn_0(
78 &mut module,
79 "arch",
80 "Get the CPU architecture (e.g. x86_64, aarch64)",
81 ConcreteType::String,
82 |ctx| {
83 crate::module_exports::check_permission(ctx, shape_abi_v1::Permission::Env)?;
84 Ok(TypedReturn::Concrete(ConcreteReturn::String(
85 std::env::consts::ARCH.to_string(),
86 )))
87 },
88 );
89
90 module
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_env_module_creation() {
99 let module = create_env_module();
100 assert_eq!(module.name, "std::core::env");
101 assert!(module.has_export("has"));
102 assert!(module.has_export("cwd"));
103 assert!(module.has_export("os"));
104 assert!(module.has_export("arch"));
105 }
106
107 #[test]
108 fn test_env_typed_registry_arg_kinds() {
109 let module = create_env_module();
110 let typed = module.typed_exports();
111
112 let has_entry = typed.get("has").unwrap();
116 assert_eq!(has_entry.arg_kinds.len(), 1);
117 assert_eq!(has_entry.arg_kinds[0], shape_value::NativeKind::String);
118 assert_eq!(has_entry.return_type, ConcreteType::Bool);
119
120 let cwd_entry = typed.get("cwd").unwrap();
122 assert!(cwd_entry.arg_kinds.is_empty());
123 assert_eq!(cwd_entry.return_type, ConcreteType::String);
124 }
125
126 #[test]
127 fn test_env_schemas() {
128 let module = create_env_module();
129 let has_schema = module.get_schema("has").unwrap();
130 assert_eq!(has_schema.params.len(), 1);
131 assert_eq!(has_schema.return_type.as_deref(), Some("bool"));
132
133 let os_schema = module.get_schema("os").unwrap();
134 assert_eq!(os_schema.return_type.as_deref(), Some("string"));
135 }
136}