Skip to main content

mechanism

Attribute Macro mechanism 

Source
#[mechanism]
Expand description

Concise route declaration for toolkit-zero socket-server routes.

Replaces an async fn item with a server.mechanism(…) statement at the point of declaration. The function body is transplanted verbatim into the .onconnect(…) closure; all variables from the enclosing scope are accessible via move capture.

§Syntax

#[mechanism(server, METHOD, "/path")]
#[mechanism(server, METHOD, "/path", json)]
#[mechanism(server, METHOD, "/path", query)]
#[mechanism(server, METHOD, "/path", encrypted(key_expr))]
#[mechanism(server, METHOD, "/path", encrypted_query(key_expr))]
#[mechanism(server, METHOD, "/path", state(state_expr))]
#[mechanism(server, METHOD, "/path", state(state_expr), json)]
#[mechanism(server, METHOD, "/path", state(state_expr), query)]
#[mechanism(server, METHOD, "/path", state(state_expr), encrypted(key_expr))]
#[mechanism(server, METHOD, "/path", state(state_expr), encrypted_query(key_expr))]

The first three arguments (server, METHOD, "/path") are positional. json, query, state(…), encrypted(…), and encrypted_query(…) may appear in any order after the path.

§Parameters

ArgumentMeaning
serverIdentifier of the Server variable in the enclosing scope
METHODHTTP method: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
"/path"Route path string literal
jsonJSON-deserialised body; fn has one param (body: T)
queryURL query params; fn has one param (params: T)
encrypted(key)VEIL-encrypted body; fn has one param (body: T)
encrypted_query(key)VEIL-encrypted query; fn has one param (params: T)
state(expr)State injection; fn first param is (state: S)

When state is combined with a body mode the function receives two parameters: the state clone first, the body or query second.

§Function signature

The decorated function:

  • May be async or non-async — it is always wrapped in async move { … }.
  • May carry a return type annotation or none — it is ignored; Rust infers the return type from the reply! macro inside the body.
  • Must have exactly the number of parameters described in the table above.

§Example

use toolkit_zero::socket::server::{Server, mechanism, reply, Status, SerializationKey};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};

#[derive(Deserialize, Serialize, Clone)] struct Item { id: u32, name: String }
#[derive(Deserialize)]                  struct NewItem { name: String }
#[derive(Deserialize)]                  struct Filter { page: u32 }

#[tokio::main]
async fn main() {
    let mut server = Server::default();
    let db: Arc<Mutex<Vec<Item>>> = Arc::new(Mutex::new(vec![]));

    // Plain GET — no body, no state
    #[mechanism(server, GET, "/health")]
    async fn health() { reply!() }

    // POST — JSON body
    #[mechanism(server, POST, "/items", json)]
    async fn create_item(body: NewItem) {
        reply!(json => Item { id: 1, name: body.name }, status => Status::Created)
    }

    // GET — query params
    #[mechanism(server, GET, "/items", query)]
    async fn list_items(filter: Filter) {
        let _ = filter.page;
        reply!()
    }

    // GET — state + query
    #[mechanism(server, GET, "/items/all", state(db.clone()), query)]
    async fn list_all(db: Arc<Mutex<Vec<Item>>>, filter: Filter) {
        let items = db.lock().unwrap().clone();
        reply!(json => items)
    }

    // POST — state + JSON body
    #[mechanism(server, POST, "/items/add", state(db.clone()), json)]
    async fn add_item(db: Arc<Mutex<Vec<Item>>>, body: NewItem) {
        let id = db.lock().unwrap().len() as u32 + 1;
        let item = Item { id, name: body.name };
        db.lock().unwrap().push(item.clone());
        reply!(json => item, status => Status::Created)
    }

    // POST — VEIL-encrypted body
    #[mechanism(server, POST, "/secure", encrypted(SerializationKey::Default))]
    async fn secure_post(body: NewItem) {
        reply!(json => Item { id: 99, name: body.name })
    }

    server.serve(([127, 0, 0, 1], 8080)).await;
}