1#![allow(clippy::mutable_key_type, clippy::cloned_ref_to_slice_refs)]
2mod arithmetic;
3mod bitwise;
4mod bytevector;
5mod comparison;
6mod context;
7mod crypto;
8mod csv_ops;
9mod datetime;
10#[cfg(not(target_arch = "wasm32"))]
11mod http;
12#[cfg(not(target_arch = "wasm32"))]
13mod io;
14pub(crate) mod json;
15#[cfg(not(target_arch = "wasm32"))]
16mod kv;
17mod list;
18mod map;
19mod math;
20mod meta;
21#[cfg(not(target_arch = "wasm32"))]
22mod pdf;
23mod pio;
24mod predicates;
25mod regex_ops;
26#[cfg(not(target_arch = "wasm32"))]
27mod server;
28#[cfg(not(target_arch = "wasm32"))]
29mod sqlite;
30mod stream;
31mod string;
32#[cfg(not(target_arch = "wasm32"))]
33mod system;
34#[cfg(not(target_arch = "wasm32"))]
35mod terminal;
36mod text;
37mod toml_ops;
38mod typed_array;
39
40use sema_core::{Caps, Env, Sandbox, Value};
41
42pub fn register_stdlib(env: &Env, sandbox: &Sandbox) {
43 arithmetic::register(env);
44 comparison::register(env);
45 context::register(env);
46 list::register(env);
47 string::register(env);
48 predicates::register(env);
49 map::register(env);
50 #[cfg(not(target_arch = "wasm32"))]
51 io::register(env, sandbox);
52 math::register(env);
53 #[cfg(not(target_arch = "wasm32"))]
54 system::register(env, sandbox);
55 json::register(env);
56 toml_ops::register(env);
57 meta::register(env);
58 regex_ops::register(env);
59 #[cfg(not(target_arch = "wasm32"))]
60 http::register(env, sandbox);
61 #[cfg(not(target_arch = "wasm32"))]
62 server::register(env, sandbox);
63 bitwise::register(env);
64 crypto::register(env);
65 datetime::register(env);
66 csv_ops::register(env);
67 bytevector::register(env);
68 #[cfg(not(target_arch = "wasm32"))]
69 terminal::register(env);
70 text::register(env);
71 stream::register(env);
72 pio::register(env);
73 typed_array::register(env);
74 #[cfg(not(target_arch = "wasm32"))]
75 stream::register_io(env, sandbox);
76 #[cfg(not(target_arch = "wasm32"))]
77 kv::register(env, sandbox);
78 #[cfg(not(target_arch = "wasm32"))]
79 pdf::register(env, sandbox);
80 #[cfg(not(target_arch = "wasm32"))]
81 sqlite::register(env, sandbox);
82}
83
84fn register_fn_gated(
85 env: &Env,
86 sandbox: &Sandbox,
87 cap: Caps,
88 name: &str,
89 f: impl Fn(&[Value]) -> Result<Value, sema_core::SemaError> + 'static,
90) {
91 if sandbox.is_unrestricted() {
92 register_fn(env, name, f);
93 } else {
94 let sandbox = sandbox.clone();
95 let fn_name = name.to_string();
96 register_fn(env, name, move |args| {
97 sandbox.check(cap, &fn_name)?;
98 f(args)
99 });
100 }
101}
102
103fn register_fn_path_gated(
104 env: &Env,
105 sandbox: &Sandbox,
106 cap: Caps,
107 name: &str,
108 path_args: &[usize],
109 f: impl Fn(&[Value]) -> Result<Value, sema_core::SemaError> + 'static,
110) {
111 if sandbox.is_unrestricted() {
112 register_fn(env, name, f);
113 } else {
114 let sandbox = sandbox.clone();
115 let fn_name = name.to_string();
116 let path_indices: Vec<usize> = path_args.to_vec();
117 register_fn(env, name, move |args| {
118 sandbox.check(cap, &fn_name)?;
119 for &idx in &path_indices {
120 if let Some(val) = args.get(idx) {
121 if let Some(p) = val.as_str() {
122 sandbox.check_path(p, &fn_name)?;
123 }
124 }
125 }
126 f(args)
127 });
128 }
129}
130
131fn register_fn(
132 env: &Env,
133 name: &str,
134 f: impl Fn(&[Value]) -> Result<Value, sema_core::SemaError> + 'static,
135) {
136 env.set(
137 sema_core::intern(name),
138 Value::native_fn(sema_core::NativeFn::simple(name, f)),
139 );
140}