NAC_Blockchain/cargo-constitution/src/utils/const_loader.rs

106 lines
2.7 KiB
Rust

//! 宪法状态文件加载工具
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
/// 宪法状态文件结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConstitutionalState {
pub version: String,
#[serde(default)]
pub timestamp: Option<String>,
#[serde(default)]
pub constitutional_hash: Option<String>,
pub parameters: Vec<Parameter>,
pub clauses: Vec<Clause>,
#[serde(default)]
pub predicates: serde_json::Value,
}
/// 宪法参数
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
#[serde(default)]
pub value: serde_json::Value,
pub rust_type: String,
pub clause: String,
#[serde(default)]
pub description: Option<String>,
}
/// 宪法条款
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Clause {
pub id: String,
pub level: String,
pub title: String,
#[serde(default)]
pub predicate_hash: Option<String>,
#[serde(default)]
pub depends_on: Vec<String>,
}
/// 加载宪法状态文件
pub fn load_constitutional_state<P: AsRef<Path>>(path: P) -> Result<ConstitutionalState, String> {
let content = fs::read_to_string(path).map_err(|e| e.to_string())?;
serde_json::from_str(&content).map_err(|e| e.to_string())
}
/// 查找宪法状态文件
pub fn find_constitutional_state_file<P: AsRef<Path>>(start_dir: P) -> Option<std::path::PathBuf> {
let mut current = start_dir.as_ref().to_path_buf();
loop {
let state_file = current.join("constitutional_state.json");
if state_file.exists() {
return Some(state_file);
}
// 向上查找父目录
if !current.pop() {
break;
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn test_load_constitutional_state() {
let json = r#"{
"version": "1.0.0",
"parameters": [
{
"name": "CBPP_DT_MIN",
"value": 100,
"rust_type": "u64",
"clause": "CONS_FLUID_BLOCK"
}
],
"clauses": [
{
"id": "CONS_FLUID_BLOCK",
"level": "eternal",
"title": "流动区块生产"
}
]
}"#;
let mut temp_file = NamedTempFile::new().unwrap();
temp_file.write_all(json.as_bytes()).unwrap();
let state = load_constitutional_state(temp_file.path()).unwrap();
assert_eq!(state.version, "1.0.0");
assert_eq!(state.parameters.len(), 1);
assert_eq!(state.clauses.len(), 1);
}
}