Skip to main content

formal_ai/
shared_memory.rs

1use std::ffi::OsStr;
2use std::fs::{self, OpenOptions};
3use std::io;
4use std::path::PathBuf;
5
6pub const MEMORY_PATH_ENV: &str = "FORMAL_AI_MEMORY_PATH";
7pub const MEMORY_DIRECTORY_NAME: &str = ".formal-ai";
8pub const MEMORY_FILE_NAME: &str = "memory.lino";
9
10#[must_use]
11pub fn resolve_memory_path_from(
12    memory_path: Option<&OsStr>,
13    home: Option<&OsStr>,
14    app_data: Option<&OsStr>,
15    windows: bool,
16) -> PathBuf {
17    if let Some(path) = memory_path
18        .filter(|value| !value.to_string_lossy().trim().is_empty())
19        .map(PathBuf::from)
20    {
21        return path;
22    }
23
24    if windows {
25        return app_data
26            .or(home)
27            .map_or_else(|| PathBuf::from("."), PathBuf::from)
28            .join("formal-ai")
29            .join(MEMORY_FILE_NAME);
30    }
31
32    home.map_or_else(|| PathBuf::from("."), PathBuf::from)
33        .join(MEMORY_DIRECTORY_NAME)
34        .join(MEMORY_FILE_NAME)
35}
36
37#[must_use]
38pub fn shared_memory_path() -> PathBuf {
39    resolve_memory_path_from(
40        std::env::var_os(MEMORY_PATH_ENV).as_deref(),
41        std::env::var_os("HOME").as_deref(),
42        std::env::var_os("APPDATA").as_deref(),
43        cfg!(windows),
44    )
45}
46
47pub fn ensure_shared_memory_file(path: &std::path::Path) -> io::Result<()> {
48    if let Some(parent) = path
49        .parent()
50        .filter(|parent| !parent.as_os_str().is_empty())
51    {
52        #[cfg(unix)]
53        let existed = parent.exists();
54        fs::create_dir_all(parent)?;
55        #[cfg(unix)]
56        if !existed {
57            use std::os::unix::fs::PermissionsExt;
58            fs::set_permissions(parent, fs::Permissions::from_mode(0o700))?;
59        }
60    }
61    OpenOptions::new().create(true).append(true).open(path)?;
62    Ok(())
63}