formal_ai/
shared_memory.rs1use 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}