use std::time::Duration;
const DEFAULT_TIMEOUT_SECS: u64 = 30;
const DEFAULT_MAX_MEMORY_BYTES: u64 = 50 * 1024 * 1024;
const EPOCH_INTERVAL_MILLIS: u64 = 10;
#[derive(Debug, Clone)]
pub struct WasmConfig {
pub timeout_secs: u64,
pub max_memory_bytes: u64,
}
impl Default for WasmConfig {
fn default() -> Self {
Self {
timeout_secs: DEFAULT_TIMEOUT_SECS,
max_memory_bytes: DEFAULT_MAX_MEMORY_BYTES,
}
}
}
impl WasmConfig {
pub fn from_uri(uri_without_scheme: &str) -> (String, WasmConfig) {
let (path, query) = match uri_without_scheme.find('?') {
Some(i) => (&uri_without_scheme[..i], Some(&uri_without_scheme[i + 1..])),
None => (uri_without_scheme, None),
};
let mut config = WasmConfig::default();
if let Some(q) = query {
for pair in q.split('&') {
if let Some((key, value)) = pair.split_once('=') {
match key {
"timeout" => {
if let Ok(secs) = value.parse::<u64>()
&& secs > 0
{
config.timeout_secs = secs;
}
}
"max-memory" => {
if let Ok(bytes) = value.parse::<u64>()
&& bytes > 0
{
config.max_memory_bytes = bytes;
}
}
_ => {} }
}
}
}
(path.to_string(), config)
}
pub fn epoch_deadline(&self) -> u64 {
self.timeout_secs * (1000 / EPOCH_INTERVAL_MILLIS)
}
pub fn epoch_interval(&self) -> Duration {
Duration::from_millis(EPOCH_INTERVAL_MILLIS)
}
pub fn epoch_interval_millis(&self) -> u64 {
EPOCH_INTERVAL_MILLIS
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = WasmConfig::default();
assert_eq!(config.timeout_secs, 30);
assert_eq!(config.max_memory_bytes, 50 * 1024 * 1024);
}
#[test]
fn test_from_uri_no_params() {
let (path, config) = WasmConfig::from_uri("plugins/test.wasm");
assert_eq!(path, "plugins/test.wasm");
assert_eq!(config.timeout_secs, 30);
assert_eq!(config.max_memory_bytes, 50 * 1024 * 1024);
}
#[test]
fn test_from_uri_with_timeout() {
let (path, config) = WasmConfig::from_uri("plugins/test.wasm?timeout=10");
assert_eq!(path, "plugins/test.wasm");
assert_eq!(config.timeout_secs, 10);
assert_eq!(config.max_memory_bytes, 50 * 1024 * 1024);
}
#[test]
fn test_from_uri_with_max_memory() {
let (path, config) = WasmConfig::from_uri("plugins/test.wasm?max-memory=10485760");
assert_eq!(path, "plugins/test.wasm");
assert_eq!(config.timeout_secs, 30);
assert_eq!(config.max_memory_bytes, 10_485_760);
}
#[test]
fn test_from_uri_with_both_params() {
let (path, config) = WasmConfig::from_uri("plugins/test.wasm?timeout=5&max-memory=1048576");
assert_eq!(path, "plugins/test.wasm");
assert_eq!(config.timeout_secs, 5);
assert_eq!(config.max_memory_bytes, 1_048_576);
}
#[test]
fn test_from_uri_ignores_unknown_params() {
let (path, config) = WasmConfig::from_uri("plugins/test.wasm?foo=bar&timeout=60");
assert_eq!(path, "plugins/test.wasm");
assert_eq!(config.timeout_secs, 60);
}
#[test]
fn test_from_uri_ignores_invalid_values() {
let (_path, config) = WasmConfig::from_uri("plugins/test.wasm?timeout=abc");
assert_eq!(config.timeout_secs, 30); }
#[test]
fn test_from_uri_ignores_zero_values() {
let (_path, config) = WasmConfig::from_uri("plugins/test.wasm?timeout=0&max-memory=0");
assert_eq!(config.timeout_secs, 30); assert_eq!(config.max_memory_bytes, 50 * 1024 * 1024); }
#[test]
fn test_epoch_deadline() {
let config = WasmConfig {
timeout_secs: 30,
max_memory_bytes: 0,
};
assert_eq!(config.epoch_deadline(), 3000); }
#[test]
fn test_epoch_deadline_custom_timeout() {
let config = WasmConfig {
timeout_secs: 5,
max_memory_bytes: 0,
};
assert_eq!(config.epoch_deadline(), 500);
}
#[test]
fn test_epoch_interval() {
let config = WasmConfig::default();
assert_eq!(config.epoch_interval(), Duration::from_millis(10));
}
}