Skip to main content

sema_stdlib/
lib.rs

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