From 2372495e1a0acb9ffead7651d8ed36a3bb98a15b Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 18 Mar 2026 11:19:51 +0800 Subject: Add new protocol crate with basic types and operations --- systems/_constants/src/lib.rs | 33 +++++++--- systems/workspace/Cargo.toml | 1 + systems/workspace/src/workspace/manager.rs | 1 + .../workspace/src/workspace/manager/sheet_state.rs | 73 ++++++++++++++++++++++ 4 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 systems/workspace/src/workspace/manager/sheet_state.rs (limited to 'systems') diff --git a/systems/_constants/src/lib.rs b/systems/_constants/src/lib.rs index b9d313c..e576be3 100644 --- a/systems/_constants/src/lib.rs +++ b/systems/_constants/src/lib.rs @@ -14,7 +14,7 @@ pub mod server { /// File constants #[constants_macros::constants("server_file")] pub mod files { - c! { CONFIG = "config.toml" } + c! { CONFIG = "server.toml" } // Storage location for keys and passwords c! { KEY = "auth/key/{member_name}.pem" } @@ -114,10 +114,13 @@ pub mod workspace { // ### Sheets ### // Records the latest state of local physical files, used to calculate deviations - c! { LOCAL_STATUS = ".jv/sheets/{account}/{sheet}.local" } + c! { LOCAL_STATUS = ".jv/sheets/{sheet}.local" } // Personal sheet, represents the desired file structure, held only by the member, can be backed up to the vault - c! { SHEET = ".jv/sheets/{account}/{sheet}.sheet" } + c! { SHEET = ".jv/sheets/{sheet}.sheet" } + + // Current sheet name + c! { CURRENT_SHEET = ".jv/sheets/CURRENT" } // Draft file, when switching to another sheet, fully records modified but untracked files c! { DRAFTED_FILE = ".jv/drafts/{account}_{sheet}/{mapping}" } @@ -131,7 +134,7 @@ pub mod workspace { pub mod dirs { c! { WORKSPACE = ".jv" } c! { VAULT_MIRROR = ".jv/UPSTREAM/" } - c! { LOCAL_SHEETS = ".jv/sheets/{account}/" } + c! { LOCAL_SHEETS = ".jv/sheets/" } c! { DRAFT_AREA = ".jv/drafts/{account}_{sheet}/" } c! { ID_MAPPING = ".jv/idmp/" } c! { WORKING_AREA = "" } @@ -141,26 +144,36 @@ pub mod workspace { /// File and directory path constants for the user root #[allow(unused)] pub mod user { + /// Others + #[constants_macros::constants("user_value")] + pub mod values { + c! { USER_CONFIG_NAME = "usr.toml" } + } + /// File path constants #[constants_macros::constants("user_file")] pub mod files { // Upstream public key, stored after initial login, used to verify the trustworthiness of that upstream - c! { UPSTREAM_PUB = "upstreams/{upstream_addr}.pem" } + c! { JVCS_UPSTREAM_PUB = ".jvcs/upstreams/{jvcs_upstream_addr}.pem" } // Account private key, stored only locally, used for login authentication - c! { PRIVATE_KEY = "private/{account}.pem" } + c! { PRIVATE_KEY = ".jvcs/private/{account}.pem" } // Account public key, automatically generated from the private key and stored, // will be placed into the server's "join request list" upon initial login (if server.toml permits this action) // The server administrator can optionally approve this request - c! { PUBLIC_KEY = "public/{account}.pem" } + c! { PUBLIC_KEY = ".jvcs/public/{account}.pem" } + + // Account configuration file + c! { USER_CONFIG = ".jvcs/usr.toml" } } /// Directory path constants #[constants_macros::constants("user_dir")] pub mod dirs { - c! { UPSTREAM_PUBS = "upstreams/" } - c! { PRIVATE_KEYS = "private/" } - c! { PUBLIC_KEYS = "public/" } + c! { ROOT = ".jvcs/" } + c! { UPSTREAM_PUBS = ".jvcs/upstreams/" } + c! { PRIVATE_KEYS = ".jvcs/private/" } + c! { PUBLIC_KEYS = ".jvcs/public/" } } } diff --git a/systems/workspace/Cargo.toml b/systems/workspace/Cargo.toml index c601370..90690f8 100644 --- a/systems/workspace/Cargo.toml +++ b/systems/workspace/Cargo.toml @@ -10,6 +10,7 @@ constants = { path = "../_constants" } framework = { path = "../_framework" } sheet_system = { path = "../sheet" } +just_fmt.workspace = true serde.workspace = true thiserror.workspace = true tokio.workspace = true diff --git a/systems/workspace/src/workspace/manager.rs b/systems/workspace/src/workspace/manager.rs index adee9b7..58eb409 100644 --- a/systems/workspace/src/workspace/manager.rs +++ b/systems/workspace/src/workspace/manager.rs @@ -4,6 +4,7 @@ use constants::workspace::files::workspace_file_config; use framework::space::Space; pub mod id_aliases; +pub mod sheet_state; pub struct WorkspaceManager { space: Space, diff --git a/systems/workspace/src/workspace/manager/sheet_state.rs b/systems/workspace/src/workspace/manager/sheet_state.rs new file mode 100644 index 0000000..5603adf --- /dev/null +++ b/systems/workspace/src/workspace/manager/sheet_state.rs @@ -0,0 +1,73 @@ +use std::path::PathBuf; + +use crate::workspace::manager::WorkspaceManager; +use asset_system::asset::ReadOnlyAsset; +use constants::workspace::files::{workspace_file_current_sheet, workspace_file_sheet}; +use framework::space::error::SpaceError; +use just_fmt::snake_case; +use sheet_system::sheet::{Sheet, SheetData}; + +impl WorkspaceManager { + /// Read the name of the currently active Sheet + pub async fn using_sheet_name(&self) -> Result, SpaceError> { + match self + .space + .read_to_string(workspace_file_current_sheet()) + .await + { + Ok(s) => Ok(Some(s.trim().to_string())), + Err(SpaceError::Io(io_error)) => match io_error.kind() { + std::io::ErrorKind::NotFound => Ok(None), + _ => Err(SpaceError::Io(io_error)), + }, + Err(e) => Err(e), + } + } + + /// Set the name of the currently active Sheet + pub async fn edit_using_sheet_name(&self, name: &str) -> Result<(), SpaceError> { + self.space + .write(workspace_file_current_sheet(), name.as_bytes()) + .await + } + + /// Read a sheet from the workspace space by name + /// + /// Simple read of Sheet data, no disk write operations involved + pub async fn read_sheet(&self, sheet_name: &str) -> Option { + let sheet_name = snake_case!(sheet_name); + let sheet_path = self.get_sheet_path(&sheet_name); + + let mut sheet_data = SheetData::empty(); + if sheet_path.exists() { + // If reading fails, treat it as if the sheet does not exist and return `None` + sheet_data.full_read(sheet_path).await.ok()?; + return Some(sheet_data.pack(sheet_name)); + } else { + None + } + } + + /// Get a resource pointing to local Sheet data by name + /// + /// Can be used to load content, edit, and transactionally write + pub fn get_sheet_data_asset(&self, sheet_name: &str) -> Option> { + let sheet_name = snake_case!(sheet_name); + let sheet_path = self.get_sheet_path(&sheet_name); + if sheet_path.exists() { + return Some(sheet_path.into()); + } + None + } + + /// Get the local filesystem path for a sheet by name + pub fn get_sheet_path(&self, sheet_name: impl AsRef) -> PathBuf { + let sheet_name = sheet_name.as_ref(); + self.space + .local_path(workspace_file_sheet(&sheet_name)) + // The `local_path` only produces path formatting errors. + // If the path cannot be guaranteed to be correct, + // execution should not continue, so we unwrap() + .unwrap() + } +} -- cgit