nutex 0.1.3

Nutex stands for NUllable muTEX: mutex that may contain value that doesn't exist.
Documentation

What the actual fuck is "Nutex"?

Nutex stands for NUllable muTEX. It's intended for the global states that cannot provide the value at the start of the app runtime and gives a convenient access to nullable value.

Why not just Mutex<Option<T>>?

You may use that, but it's very inconvenient.

For example, you created an app and you want to access and process the user client data stored in mutex in the some function that may be called only if user is logged in. With using the standard Tokio mutex you should unwrap the value all the time:

pub struct AppState {
    pub client: Mutex<Option<Client>>,
    // ...
}

#[tauri::command]
pub async fn send_message(
    state: State<'_, AppState>,
    message: String,
    to: RecId
) -> Result<(), SendError> {
    // ? You need to do THIS:
    state
        .client
        .lock()
        .await
        .expect("User must be logged in, blah, blah, blah...")
        .user_id()
        .expect("User must be logged in, blah blah blah...")
        .process()
        .yet_another_process()
        .et_cetera();
    // ...
    Ok(())
}

#[tauri::command]
pub async fn register(
    state: State<'_, AppState>,
    auth_data: AuthData,
) -> Result<(), ErrorResponse> {
    // ? And THIS...
    state.client.lock().await = Some(
        Client::builder()
            .register(auth_data)
            .build()
            .await?
            .map_err(/* ... */)?;
    )
    // ...
    Ok(())
}

Double checking. Double headache. But Nutex gives you this:

pub struct AppState {
    pub client: Nutex<Client>,
    // ...
}

#[tauri::command]
pub async fn send_message(
    state: State<'_, AppState>,
    message: String,
    to: RecId
) -> Result<(), SendError> {
    state
        .client
        .lock()
        .await
        .user_id()
        .expect("User must be logged in, blah blah blah...")
        .process();
    // ...
    Ok(())
}

#[tauri::command]
pub async fn register(
    state: State<'_, AppState>,
    auth_data: AuthData,
) -> Result<(), ErrorResponse> {
    state.client.set(
        Client::builder()
            .register(auth_data)
            .build()
            .await?
            .map_err(/* ... */)?;
            // ...
    ).await;
    Ok(())
}

It simplifies the code a lot because Mutexes frequently used with values that cannot be known at the time when they are created.


And how I need to use the Nutex?

If you certainly know that value is not None, then you can just lock the Nutex and access the value:

let nutex = Nutex::from(String::from("foo"));
*nutex.lock().await = String::from("bar");
assert_eq!(String::from("bar"), *nutex.lock().await);

But if you're not sure that it's not None, prefer using Nutex::safe_lock:

if let Some(mut guard) = nutex.safe_lock().await {
    *guard = String::from("foo");
}

Other documentation about Nutex may be found in the tokio::sync::Mutex docs: Nutex is just a wrapper for this anyway.