From 4f184a439056d2b5dff7aa2fa1b1a73a1cbe9582 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 7 Feb 2026 18:08:42 +0800 Subject: Add asset system with file locking and atomic writes --- systems/asset/src/rw.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 systems/asset/src/rw.rs (limited to 'systems/asset/src/rw.rs') diff --git a/systems/asset/src/rw.rs b/systems/asset/src/rw.rs new file mode 100644 index 0000000..784d44d --- /dev/null +++ b/systems/asset/src/rw.rs @@ -0,0 +1,85 @@ +use std::path::PathBuf; + +use crate::error::{DataReadError, DataWriteError}; + +pub trait RWData { + type DataType; + + /// Implement read logic + /// Given a path, return the specific data + fn read(path: &PathBuf) -> impl Future> + Send + Sync; + + /// Implement write logic + /// Given data and a path, write to the filesystem + fn write( + data: DataType, + path: &PathBuf, + ) -> impl Future> + Send + Sync; + + /// Provide test data + fn test_data() -> DataType; + + /// Given two sets of data, determine if they are equal + /// + /// Add RWDataTest derive to your struct to automatically generate tests + /// ```ignore + /// #[derive(RWDataTest)] + /// struct FooData; + /// ``` + fn verify_data(data_a: DataType, data_b: DataType) -> bool; +} + +#[macro_export] +macro_rules! ensure_eq { + ($a:expr, $b:expr) => { + if $a != $b { + return false; + } + }; +} + +// Test Data +pub struct FooData { + pub age: i32, + pub name: String, +} + +impl RWData for FooData { + type DataType = FooData; + + async fn read(path: &PathBuf) -> Result { + let content = tokio::fs::read_to_string(path) + .await + .map_err(|e| DataReadError::IoError(e))?; + let parts: Vec<&str> = content.split('=').collect(); + if parts.len() != 2 { + return Err(DataReadError::ParseError("Invalid format".to_string())); + } + let name = parts[0].to_string(); + let age: i32 = parts[1] + .parse() + .map_err(|_| DataReadError::ParseError("Invalid age".to_string()))?; + Ok(FooData { age, name }) + } + + async fn write(data: FooData, path: &PathBuf) -> Result<(), DataWriteError> { + let content = format!("{}={}", data.name, data.age); + tokio::fs::write(path, content) + .await + .map_err(|e| DataWriteError::IoError(e))?; + Ok(()) + } + + fn test_data() -> FooData { + FooData { + age: 24, + name: "OneOneFourFiveOneFour".to_string(), + } + } + + fn verify_data(data_a: FooData, data_b: FooData) -> bool { + crate::ensure_eq!(data_a.age, data_b.age); + crate::ensure_eq!(data_a.name, data_b.name); + return true; + } +} -- cgit