定义数据库结构体

首先,我们需要创建数据库结构体。 通常它只会被应用程序的“驱动代码”使用, 也就是负责启动程序、提供输入并转发输出的那一部分。

calc 中,数据库结构体位于 db 模块里,形式如下:

#![allow(unused)]
fn main() {
#[salsa::db]
#[derive(Clone)]
#[cfg_attr(not(test), derive(Default))]
pub struct CalcDatabaseImpl {
    storage: salsa::Storage<Self>,

    // The logs are only used for testing and demonstrating reuse:
    #[cfg(test)]
    logs: Arc<Mutex<Option<Vec<String>>>>,
}

#[cfg(test)]
impl Default for CalcDatabaseImpl {
    fn default() -> Self {
        let logs = <Arc<Mutex<Option<Vec<String>>>>>::default();
        Self {
            storage: salsa::Storage::new(Some(Box::new({
                let logs = logs.clone();
                move |event| {
                    eprintln!("Event: {event:?}");
                    // Log interesting events, if logging is enabled
                    if let Some(logs) = &mut *logs.lock().unwrap() {
                        // only log interesting events
                        if let salsa::EventKind::WillExecute { .. } = event.kind {
                            logs.push(format!("Event: {event:?}"));
                        }
                    }
                }
            }))),
            logs,
        }
    }
}
}

#[salsa::db] 属性会把这个结构体标记为数据库。 它必须包含一个名为 storage 的字段,其类型为 salsa::Storage<Self>, 但你也可以根据需要添加其他字段。

实现 salsa::Database trait

除了结构体本身,我们还必须实现 salsa::Database

#![allow(unused)]
fn main() {
#[salsa::db]
impl salsa::Database for CalcDatabaseImpl {}
}