summaryrefslogtreecommitdiff
path: root/src/app.rs
blob: 43e2ac680dd02d33e55eefdfd1108e6fe353c2f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//! Internal app logic.

use crate::session::Session;
use std::collections::HashMap;
use std::sync::{Mutex, MutexGuard, RwLock};

/// Provider of the state that Tabletop Ambulator needs to keep track of.
///
/// Provides the app state, including runtime data such as the active game
/// sessions. It provides access to relevant data through synchronization
/// primitives, but does not handle shared ownership; for that, you may
/// want to use a solution like [`std::sync::Arc`].
#[derive(Debug, Default)]
pub struct AppState {
    sessions: RwLock<HashMap<String, Mutex<Session>>>,
}

impl AppState {
    /// Creates a new `AppState`.
    pub fn new() -> Self {
        Self::default()
    }

    /// Creates and stores a new [`Session`], which can later be accessed with [`with_session`].
    pub fn create_session(&self, id: String, name: String) {
        let session = Mutex::new(Session::new(name));
        self.sessions.write().unwrap().insert(id, session);
    }

    /// Finds a [`Session`] by the provided `id`. If the session exists, it is provided within a
    /// [`MutexGuard`] to the supplied function. Returns the result of the function, or `None` if
    /// there was no session with the supplied id.
    pub fn with_session<T>(&self, id: &str, f: impl FnOnce(MutexGuard<Session>) -> T) -> Option<T> {
        let sessions = self.sessions.read().unwrap();
        sessions.get(id).map(|session| f(session.lock().unwrap()))
    }
}