Skip to main content

pepl_stdlib/modules/
storage.rs

1//! `storage` capability module — persistent key-value storage (host-delegated).
2//!
3//! Functions: get, set, delete, keys.
4//! All storage operations are host-delegated — the runtime host manages actual
5//! persistence via `env.host_call(cap_id=2, fn_id, payload)`. This module
6//! validates arguments and returns `CapabilityCall` errors to signal the
7//! caller to route the call to the host.
8//!
9//! # Cap ID / Fn ID Mapping
10//!
11//! | fn_id | Function |
12//! |-------|----------|
13//! | 1     | get      |
14//! | 2     | set      |
15//! | 3     | delete   |
16//! | 4     | keys     |
17
18use crate::capability::{CAP_STORAGE, STORAGE_DELETE, STORAGE_GET, STORAGE_KEYS, STORAGE_SET};
19use crate::error::StdlibError;
20use crate::module::StdlibModule;
21use crate::value::Value;
22
23/// The `storage` capability module.
24pub struct StorageModule;
25
26impl StorageModule {
27    pub fn new() -> Self {
28        Self
29    }
30}
31
32impl Default for StorageModule {
33    fn default() -> Self {
34        Self::new()
35    }
36}
37
38impl StdlibModule for StorageModule {
39    fn name(&self) -> &'static str {
40        "storage"
41    }
42
43    fn has_function(&self, function: &str) -> bool {
44        matches!(function, "get" | "set" | "delete" | "keys")
45    }
46
47    fn call(&self, function: &str, args: Vec<Value>) -> Result<Value, StdlibError> {
48        match function {
49            "get" => self.get(args),
50            "set" => self.set(args),
51            "delete" => self.delete(args),
52            "keys" => self.keys(args),
53            _ => Err(StdlibError::unknown_function("storage", function)),
54        }
55    }
56}
57
58impl StorageModule {
59    /// `storage.get(key: string) -> Result<string, StorageError>`
60    ///
61    /// Validates: exactly 1 arg, must be string.
62    /// Returns `CapabilityCall` with cap_id=2, fn_id=1.
63    fn get(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
64        if args.len() != 1 {
65            return Err(StdlibError::wrong_args("storage.get", 1, args.len()));
66        }
67        validate_string("storage.get", &args[0], 1)?;
68        Err(StdlibError::capability_call(
69            "storage",
70            "get",
71            CAP_STORAGE,
72            STORAGE_GET,
73            args,
74        ))
75    }
76
77    /// `storage.set(key: string, value: string) -> Result<nil, StorageError>`
78    ///
79    /// Validates: exactly 2 args, both must be strings.
80    /// Returns `CapabilityCall` with cap_id=2, fn_id=2.
81    fn set(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
82        if args.len() != 2 {
83            return Err(StdlibError::wrong_args("storage.set", 2, args.len()));
84        }
85        validate_string("storage.set", &args[0], 1)?;
86        validate_string("storage.set", &args[1], 2)?;
87        Err(StdlibError::capability_call(
88            "storage",
89            "set",
90            CAP_STORAGE,
91            STORAGE_SET,
92            args,
93        ))
94    }
95
96    /// `storage.delete(key: string) -> Result<nil, StorageError>`
97    ///
98    /// Validates: exactly 1 arg, must be string.
99    /// Returns `CapabilityCall` with cap_id=2, fn_id=3.
100    fn delete(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
101        if args.len() != 1 {
102            return Err(StdlibError::wrong_args("storage.delete", 1, args.len()));
103        }
104        validate_string("storage.delete", &args[0], 1)?;
105        Err(StdlibError::capability_call(
106            "storage",
107            "delete",
108            CAP_STORAGE,
109            STORAGE_DELETE,
110            args,
111        ))
112    }
113
114    /// `storage.keys() -> Result<list<string>, StorageError>`
115    ///
116    /// Validates: no args.
117    /// Returns `CapabilityCall` with cap_id=2, fn_id=4.
118    fn keys(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
119        if !args.is_empty() {
120            return Err(StdlibError::wrong_args("storage.keys", 0, args.len()));
121        }
122        Err(StdlibError::capability_call(
123            "storage",
124            "keys",
125            CAP_STORAGE,
126            STORAGE_KEYS,
127            args,
128        ))
129    }
130}
131
132// ── Helpers ──────────────────────────────────────────────────────────────────
133
134fn validate_string(func: &str, val: &Value, pos: usize) -> Result<(), StdlibError> {
135    match val {
136        Value::String(_) => Ok(()),
137        _ => Err(StdlibError::type_mismatch(
138            func,
139            pos,
140            "string",
141            val.type_name(),
142        )),
143    }
144}