Rust协议处理库nu-protocol的使用,nu-protocol为Nushell提供核心协议支持与数据处理功能
Rust协议处理库nu-protocol的使用
nu-protocol
是 Nushell 生态系统中一个核心的 Rust 库,它为整个 Nushell 提供了基础协议支持和数据处理功能。
功能概述
nu-protocol crate 包含了在整个 Nushell 中使用的结构体和特性的定义。这为我们提供了一种将它们暴露给许多其他 crate 的方式,同时也使这些定义可以相互使用,而不会导致相互递归的依赖关系。
安装
要在你的项目中使用 nu-protocol,可以运行以下 Cargo 命令:
cargo add nu-protocol
或者在 Cargo.toml 中添加:
nu-protocol = "0.106.1"
使用示例
以下是一个使用 nu-protocol 的简单示例,展示了如何定义和使用 Nushell 中的基本数据类型:
use nu_protocol::{Value, ShellError, Span};
// 创建一个简单的 Value 对象
fn create_value_example() -> Value {
Value::String {
val: "Hello, Nushell!".to_string(),
span: Span::unknown(),
}
}
// 处理 Value 对象
fn process_value(value: Value) -> Result<(), ShellError> {
match value {
Value::String { val, span } => {
println!("Got string value: {}", val);
Ok(())
}
_ => Err(ShellError::type_error(
"string",
value.get_type().to_string(),
value.span()?,
)),
}
}
// 主函数
fn main() -> Result<(), ShellError> {
let value = create_value_example();
process_value(value)?;
Ok(())
}
高级示例
下面是一个更完整的示例,展示了如何使用 nu-protocol 处理 Nushell 中的管道数据:
use nu_protocol::{
engine::{Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value,
};
// 定义一个自定义命令
#[derive(Clone)]
pub struct MyCustomCommand;
impl Command for MyCustomCommand {
fn name(&self) -> &str {
"my_custom_command"
}
fn signature(&self) -> Signature {
Signature::build("my_custom_command")
.input_output_types(vec![(Type::Any, Type::Any)])
.category(Category::Experimental)
}
fn usage(&self) -> &str {
"A custom command that processes input data"
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Process some input",
example: "some_input | my_custom_command",
result: None,
}]
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
input: PipelineData,
_call_span: Span,
) -> Result<PipelineData, ShellError> {
// 处理输入数据
input.map(
|value| {
// 对每个值进行转换
match value {
Value::String { val, span } => Value::String {
val: format!("Processed: {}", val),
span,
},
Value::Int { val, span } => Value::Int {
val: val * 2,
span,
},
_ => value,
}
},
|error| error,
)
}
}
// 使用自定义命令
fn use_custom_command() -> Result<(), ShellError> {
let engine_state = EngineState::new();
let mut stack = Stack::new();
// 创建输入数据
let input = Value::String {
val: "test input".to_string(),
span: Span::unknown(),
}.into_pipeline_data();
// 执行命令
let cmd = MyCustomCommand;
let output = cmd.run(&engine_state, &mut stack, input, Span::unknown())?;
// 处理输出
if let Some(value) = output.into_value(Span::unknown()) {
println!("Command output: {:?}", value);
}
Ok(())
}
fn main() -> Result<(), ShellError> {
use_custom_command()
}
完整示例代码
以下是一个结合了基础功能和自定义命令的完整示例:
use nu_protocol::{
engine::{Command, EngineState, Stack},
Category, Example, IntoPipelineData, PipelineData, ShellError,
Signature, Span, Type, Value
};
// 自定义命令:字符串处理
#[derive(Clone)]
pub struct StringProcessor;
impl Command for StringProcessor {
fn name(&self) -> &str {
"str_process"
}
fn signature(&self) -> Signature {
Signature::build("str_process")
.input_output_type(Type::String, Type::String)
.category(Category::Strings)
}
fn usage(&self) -> &str {
"Process input string by adding prefix and suffix"
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Process a string",
example: r#""hello" | str_process"#,
result: Some(Value::test_string("PREFIX:hello:SUFFIX")),
}]
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
input: PipelineData,
_call_span: Span,
) -> Result<PipelineData, ShellError> {
input.map(
|value| {
match value {
Value::String { val, span } => Value::String {
val: format!("PREFIX:{}:SUFFIX", val),
span,
},
_ => value,
}
},
|error| error,
)
}
}
// 主应用程序
fn main() -> Result<(), ShellError> {
// 初始化引擎状态和堆栈
let engine_state = EngineState::new();
let mut stack = Stack::new();
// 创建输入数据
let input = Value::String {
val: "test string".to_string(),
span: Span::unknown(),
}.into_pipeline_data();
// 创建并执行命令
let processor = StringProcessor;
let output = processor.run(&engine_state, &mut stack, input, Span::unknown())?;
// 输出结果
if let Value::String { val, .. } = output.into_value(Span::unknown()) {
println!("处理后的字符串: {}", val);
}
Ok(())
}
这个完整示例展示了:
- 如何定义一个完整的自定义命令
- 如何处理字符串输入
- 如何实现命令的签名和示例
- 如何在主程序中使用自定义命令处理数据
Rust协议处理库nu-protocol的使用指南
概述
nu-protocol
是Nushell生态系统的核心协议处理库,为Nushell提供基础数据类型、协议支持和数据处理功能。它定义了Nushell中使用的核心数据结构、值类型以及与shell交互的基本协议。
主要功能
- 提供Nushell的核心数据类型(Value, Span等)
- 定义插件协议和序列化格式
- 处理管道数据流
- 支持错误处理和诊断信息
基本使用方法
添加依赖
首先在Cargo.toml中添加依赖:
[dependencies]
nu-protocol = "0.85" # 使用最新版本
核心数据类型
nu-protocol
定义了Nushell的核心Value类型:
use nu_protocol::{Value, Span};
fn create_value() -> Value {
// 创建一个简单的整数值
Value::int(42, Span::unknown())
}
fn create_list() -> Value {
// 创建一个列表值
Value::list(
vec![
Value::int(1, Span::unknown()),
Value::string("hello", Span::unknown()),
Value::bool(true, Span::unknown()),
],
Span::unknown(),
)
}
处理插件协议
nu-protocol
提供了与Nushell插件系统交互的功能:
use nu_protocol::{
PluginSignature, Plugin, EngineInterface,
EvaluatedCall, LabeledError, Value
};
struct MyPlugin;
impl Plugin for MyPlugin {
fn signature(&self) -> Vec<PluginSignature> {
vec![PluginSignature::build("my-command")
.desc("A custom command for Nushell")
.required("input", SyntaxShape::Any, "input value")
]
}
fn run(
&mut self,
name: &str,
call: &EvaluatedCall,
input: &Value,
engine: &EngineInterface,
) -> Result<Value, LabeledError> {
// 处理命令逻辑
Ok(input.clone())
}
}
错误处理
use nu_protocol::{LabeledError, Span};
fn might_fail(input: &str) -> Result<Value, LabeledError> {
if input.is_empty() {
Err(LabeledError {
msg: "Input cannot be empty".into(),
span: Some(Span::unknown()),
labels: vec![],
help: Some("Please provide a non-empty string".into()),
})
} else {
Ok(Value::string(input.to_owned(), Span::unknown()))
}
}
自定义值类型
use nu_protocol::{CustomValue, ShellError, Span, Value};
#[derive(Debug, Clone)]
struct MyCustomValue {
data: String,
}
impl CustomValue for MyCustomValue {
fn type_name(&self) -> String {
"MyCustomValue".into()
}
fn to_base_value(&self, span: Span) -> Result<Value, ShellError> {
Ok(Value::string(self.data.clone(), span))
}
fn as_any(&self) &dyn std::any::Any {
self
}
}
高级用法
实现自定义命令
use nu_protocol::{
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value,
};
pub struct MyCommand;
impl Command for MyCommand {
fn name(&self) -> &str {
"my-command"
}
fn signature(&self) -> Signature {
Signature::build("my-command")
.input_output_types(vec![(Type::Any, Type::Any)])
.required("arg", SyntaxShape::Any, "argument description")
.category(Category::Custom("my-category".into()))
}
fn usage(&self) -> &str {
"Description of what my-command does"
}
fn examples(&self) -> Vec<Example> {
vec![Example {
description: "Example usage",
example: "my-command 42",
result: Some(Value::test_int(42)),
}]
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
// 命令实现逻辑
Ok(input)
}
}
处理管道数据
use nu_protocol::{PipelineData, Value, ShellError};
fn process_pipeline(input: PipelineData) -> Result<PipelineData, ShellError> {
input.map(move |value| {
// 对管道中的每个值进行处理
match value {
Value::Int { val, span } => Value::int(val * 2, span),
_ => value,
}
})
}
完整示例代码
下面是一个完整的Nushell插件示例,展示了如何使用nu-protocol
创建一个自定义命令:
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Type, Value,
};
// 定义一个平方命令
pub struct SquareCommand;
impl Command for SquareCommand {
fn name(&self) -> &str {
"square" // 命令名称
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![(Type::Int, Type::Int)]) // 输入输出类型
.category(Category::Math) // 命令分类
}
fn usage(&self) -> &str {
"计算输入整数的平方" // 命令描述
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "计算5的平方",
example: "5 | square",
result: Some(Value::test_int(25)),
},
]
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
// 处理输入数据
input.map(
move |value| match value {
Value::Int { val, span } => {
// 计算平方值
Value::int(val * val, span)
}
other => Value::error(
ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: call.head,
src_span: other.span(),
},
call.head,
),
},
)
}
}
总结
nu-protocol
是开发Nushell插件和扩展的核心库,提供了与Nushell交互所需的所有基础类型和协议。通过它,开发者可以:
- 创建自定义命令和插件
- 处理Nushell管道数据
- 定义自定义值类型
- 与Nushell引擎进行深度集成
对于更复杂的用例,建议参考Nushell官方文档和nu-protocol
的源代码。