# knife-util
[](https://crates.io/crates/knife-util)
[](https://docs.rs/knife-util)
[](LICENSE)
一个为 knife 项目提供通用工具和功能的 Rust 库。
## 🚀 功能特性
### 📦 核心模块
- **🔧 错误处理**: 统一的错误类型和处理机制,支持错误链和上下文信息
- **🔄 JSON合并**: 深度合并JSON数据,支持类型转换和枚举处理
- **📁 路径工具**: 自动检测工作目录和项目路径,支持开发/生产环境
- **📄 TOML工具**: TOML与JSON之间的双向转换功能
### ✨ 主要特性
- 🛡️ **类型安全**: 所有操作都是类型安全的,编译时检查
- 🔄 **深度合并**: 支持嵌套对象的递归合并
- 🎯 **智能转换**: 自动处理数字、布尔值、字符串之间的类型转换
- 📊 **枚举支持**: 支持自定义枚举类型的转换
- 🏗️ **环境感知**: 自动识别开发和生产环境
- 📚 **完整文档**: 提供详细的API文档和使用示例
## 📦 安装
在 `Cargo.toml` 中添加依赖:
```toml
[dependencies]
knife-util = "0.1.0"
```
## 🚀 快速开始
### JSON 合并
```rust
use knife_util::{AppError, merge_json};
use serde_json::json;
fn main() -> Result<(), AppError> {
let target = json!({"user": {"name": "Alice"}});
let source = json!({"user": {"email": "alice@example.com"}});
// 深度合并JSON数据
let merged = merge_json(&target, &source)?;
println!("合并结果: {}", serde_json::to_string_pretty(&merged).unwrap());
Ok(())
}
```
### 路径工具
```rust
use knife_util::{AppError, get_work_dir, is_dev_mode};
fn main() -> Result<(), AppError> {
// 获取工作目录
let work_dir = get_work_dir()?;
println!("工作目录: {:?}", work_dir);
// 检查是否为开发模式
if is_dev_mode() {
println!("当前在开发模式中");
} else {
println!("当前在生产模式中");
}
Ok(())
}
```
### TOML 转换
```rust
use knife_util::{AppError, toml_to_json, json_to_toml};
use serde_json::json;
fn main() -> Result<(), AppError> {
// TOML 到 JSON 转换
let toml_str = r#"
title = "Example"
[database]
host = "localhost"
port = 5432
"#;
let json_value = toml_to_json(toml_str)?;
println!("TOML -> JSON: {}", serde_json::to_string_pretty(&json_value).unwrap());
// JSON 到 TOML 转换
let json_data = json!({
"app": {"name": "MyApp", "version": "1.0.0"}
});
let toml_result = json_to_toml(&json_data)?;
println!("JSON -> TOML:\n{}", toml_result);
Ok(())
}
```
## 📚 API 文档
### 错误处理
#### `AppError`
统一的错误类型,支持错误链和上下文信息:
```rust
use knife_util::AppError;
// 创建基本错误
let error = AppError::new("USER_ERROR", "用户不存在");
// 添加上下文信息
let error = error.with_attribute("user_id", 123);
// 从其他错误类型创建
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
let app_error = AppError::from_error("FILE_ERROR", "文件操作失败", io_error);
```
### JSON 合并
#### `merge_json`
深度合并两个JSON值:
```rust
use knife_util::merge_json;
use serde_json::json;
let target = json!({"user": {"name": "Alice", "age": 30}});
let source = json!({"user": {"email": "alice@example.com"}, "settings": {"theme": "dark"}});
let merged = merge_json(&target, &source)?;
// 结果: {"user": {"name": "Alice", "age": 30, "email": "alice@example.com"}, "settings": {"theme": "dark"}}
```
#### 类型转换
支持基本类型之间的转换:
```rust
use knife_util::merge::try_type_conversion;
use serde_json::json;
// 数字 ↔ 字符串
let result = try_type_conversion(&json!(42), &json!("123"))?;
assert_eq!(result, json!(123));
// 布尔值 ↔ 字符串
let result = try_type_conversion(&json!(true), &json!("yes"))?;
assert_eq!(result, json!(true));
```
#### 枚举转换
支持自定义枚举类型的转换:
```rust
use knife_util::merge::try_enum_conversion;
use serde_json::json;
#[derive(Debug, Clone, PartialEq)]
enum Status {
Active,
Inactive,
}
impl std::str::FromStr for Status {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"active" | "running" => Ok(Status::Active),
"inactive" | "stopped" => Ok(Status::Inactive),
_ => Err(format!("Invalid status: {}", s))
}
}
}
impl std::fmt::Display for Status {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Status::Active => write!(f, "ACTIVE"),
Status::Inactive => write!(f, "INACTIVE"),
}
}
}
let result = try_enum_conversion::<Status>(&json!("ACTIVE"), &json!("running"))?;
assert_eq!(result, json!("ACTIVE"));
```
### 路径工具
#### `get_work_dir`
自动检测工作目录:
```rust
use knife_util::get_work_dir;
let work_dir = get_work_dir()?;
// 开发环境: /path/to/project/workspace
// 生产环境: /path/to/executable/directory
```
#### `is_dev_mode`
检查是否为开发模式:
```rust
use knife_util::is_dev_mode;
if is_dev_mode() {
println!("开发模式");
} else {
println!("生产模式");
}
```
#### `build_work_path`
构建工作路径:
```rust
use knife_util::build_work_path;
let config_path = build_work_path("config/app.toml")?;
// 结果: /path/to/workspace/config/app.toml
```
### TOML 工具
#### `toml_to_json`
将TOML字符串转换为JSON:
```rust
use knife_util::toml_to_json;
let toml_str = r#"
title = "Example"
[database]
host = "localhost"
port = 5432
"#;
let json_value = toml_to_json(toml_str)?;
```
#### `json_to_toml`
将JSON值转换为TOML字符串:
```rust
use knife_util::json_to_toml;
use serde_json::json;
let json_data = json!({
"app": {"name": "MyApp", "version": "1.0.0"},
"database": {"host": "localhost", "port": 5432}
});
let toml_str = json_to_toml(&json_data)?;
```
#### `toml_file_to_json`
从文件读取TOML并转换为JSON:
```rust
use knife_util::toml_file_to_json;
let json_value = toml_file_to_json("config.toml")?;
```
## 🛠️ 开发
### 构建
```bash
cargo build
```
### 测试
```bash
cargo test
```
### 文档
```bash
cargo doc --open
```
### 代码覆盖率
```bash
cargo tarpaulin --out stdout
```
## 📋 依赖
- `serde` - 序列化框架
- `serde_json` - JSON支持
- `anyhow` - 错误处理
- `toml` - TOML解析
- `tracing-subscriber` - 日志支持
## 🤝 贡献
欢迎贡献代码!请遵循以下步骤:
1. Fork 项目
2. 创建特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add some amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 打开 Pull Request
## 📄 许可证
本项目采用 Apache 2.0 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。
## 🔗 相关链接
- [Crates.io](https://crates.io/crates/knife-util)
- [文档](https://docs.rs/knife-util)
- [问题追踪](https://gitee.com/ocaso1987/knife-util-rust/issues)
## 📊 项目状态
- ✅ 错误处理模块
- ✅ JSON合并功能
- ✅ 路径工具
- ✅ TOML转换
- ✅ 完整测试覆盖
- ✅ 文档完善
---
**knife-util** - 让 Rust 开发更简单! 🦀