1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
use std::path::PathBuf;
use crate::error::{DataReadError, DataWriteError};
pub trait RWData<DataType> {
type DataType;
/// Implement read logic
/// Given a path, return the specific data
fn read(path: &PathBuf) -> impl Future<Output = Result<DataType, DataReadError>> + Send + Sync;
/// Implement write logic
/// Given data and a path, write to the filesystem
fn write(
data: DataType,
path: &PathBuf,
) -> impl Future<Output = Result<(), DataWriteError>> + 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<FooData> for FooData {
type DataType = FooData;
async fn read(path: &PathBuf) -> Result<FooData, DataReadError> {
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;
}
}
|