//! {{project_name}}
//!
//! {{description}}
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
/// Main state for {{project_name}}
///
/// This uses a pure functional design - all state changes
/// return new State instances rather than mutating.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct State {
pub counter: u32,
}
impl State {
/// Create new state
///
/// # Complexity
/// - Time: O(1)
/// - Cyclomatic: 1
pub fn new() -> Self {
Self { counter: 0 }
}
/// Increment counter (returns new state)
///
/// # Complexity
/// - Time: O(1)
/// - Cyclomatic: 1
pub fn increment(&self) -> Self {
Self {
counter: self.counter + 1,
}
}
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}
/// WASM entry point
///
/// # Complexity
/// - Time: O(1)
/// - Cyclomatic: 2
#[wasm_bindgen]
pub fn process(input: &str) -> Result<String, JsValue> {
let state = State::new();
let new_state = state.increment();
serde_json::to_string(&new_state)
.map(|s| format!("Processed '{}': {}", input, s))
.map_err(|e| JsValue::from_str(&e.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_state_creation() {
let state = State::new();
assert_eq!(state.counter, 0);
}
#[test]
fn test_state_increment() {
let state = State::new();
let new_state = state.increment();
assert_eq!(new_state.counter, 1);
assert_eq!(state.counter, 0); // Original unchanged
}
#[test]
fn test_process() {
let result = process("test").unwrap();
assert!(result.contains("test"));
assert!(result.contains("counter"));
}
}
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_increment_increases(count in 0u32..1000) {
let state = State { counter: count };
let new_state = state.increment();
prop_assert_eq!(new_state.counter, count + 1);
}
#[test]
fn prop_process_never_panics(input in ".*") {
let _ = process(&input);
// If we get here, no panic occurred
}
}
}