[英]How can I use rust Try trait with Option NoneError?
我编写了一个自定义协议,在其中为帧定义了自己的结构,并从字节中解析。 我的 function 接受Vec
并相应地解析元素。 为了解决无效帧,我返回一个Result<Frame>
并在字节数组上调用.get()
。 这是我的代码:
fn main(){
let emptyvec = Vec::new();
match Frame::from_bytes(emptyvec) {
Err(e) => {
println!("Received invalid frame");
},
Ok(frame) => {
println!("Received valid frame");
}
}
}
struct Frame {
txflag: u8, // indicates if chunked
msgtype: u8, // a flag for message type
sender: u8, // which node ID sent this frame?
routeoffset: u8, // size of array of route for frame
route: Vec<u8>, // a list of node IDs that frame should pass
payload: Vec<u8>, // payload data
}
impl Frame {
/// parse from raw bytes
pub fn from_bytes(bytes: &Vec<u8>) -> std::io::Result<Self> {
let txflag = bytes.get(0)?.clone();
let msgtype = bytes.get(1)?.clone();
let sender = bytes.get(2)?.clone();
let routesoffset = bytes.get(3)?.clone();
let routes = &bytes.get(4..(4+routesoffset as usize))?;
let (left, right) = bytes.split_at(2);
let data = Vec::from(right);
Ok(Frame {
txflag,
msgtype,
sender,
routeoffset: routesoffset,
route: Vec::from(routes),
payload: data
})
}
}
但是,当我尝试使用此模式时,我收到以下编译错误,并且在尝试实现该特征时,我收到一个错误,即 Try 特征不稳定。
error[E0277]: `?` couldn't convert the error to `std::io::Error`
--> src/stack/frame.rs:121:34
|
121 | let txflag = bytes.get(0)?.clone();
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `std::io::Error`
不太确定如何进行,但我想使用稳定的功能来解决这个问题。 这里的目标是能够解析字节并根据需要处理无效帧。
这可能是你想要的
use std::io::{Error, ErrorKind};
fn main() {
let emptyvec = Vec::new();
match Frame::from_bytes(&emptyvec) {
Err(e) => {
println!("Received invalid frame");
}
Ok(frame) => {
println!("Received valid frame");
}
}
}
struct Frame {
txflag: u8,
// indicates if chunked
msgtype: u8,
// a flag for message type
sender: u8,
// which node ID sent this frame?
routeoffset: u8,
// size of array of route for frame
route: Vec<u8>,
// a list of node IDs that frame should pass
payload: Vec<u8>, // payload data
}
impl Frame {
/// parse from raw bytes
pub fn from_bytes(bytes: &Vec<u8>) -> std::io::Result<Self> {
let txflag = bytes.get(0).ok_or(Error::from(ErrorKind::InvalidData))?.clone();
let msgtype = bytes.get(1).ok_or(Error::from(ErrorKind::InvalidData))?.clone();
let sender = bytes.get(2).ok_or(Error::from(ErrorKind::InvalidData))?.clone();
let routesoffset = bytes.get(3).ok_or(Error::from(ErrorKind::InvalidData))?.clone();
let routes = bytes
.get(4..(4 + routesoffset as usize))
.ok_or(Error::from(ErrorKind::InvalidData))?
.clone();
let (_, right) = bytes.split_at(2);
let data = Vec::from(right);
Ok(Frame {
txflag,
msgtype,
sender,
routeoffset: routesoffset,
route: Vec::from(routes),
payload: data,
})
}
}
这里是Rust 游乐场
你想打电话?
在Option
上。 您必须将Option
转换为Result
(如果您仍想使用?
)。
我想补充一下 Đorðe Zeljić 所说的话:
正如他已经指出的那样bytes.get(0)
的结果是std::option::Option
。 当你使用?
操作员说你已经离开了稳定的 Rust 的理由。 目前仅在不稳定的 Rust 中支持此应用程序。
如果你想保持稳定的 Rust,最好按照 Đorðe 写的去做。 如果你想继续使用?
运算符,因为它会生成更好看的代码,这是发生了什么:
Rust 有很多错误类型,每一种都只能代表它们的用途。 如果您使用的是std::io::Result
这隐式使用错误类型std::io::Error
只能表示典型的 I/O 错误。 这种类型不能代表“当我期望的时候没有价值”。 这就是为什么从申请?
对于具有None
值的Option
,您不会得到std::io::Error
而是另一种错误: std::option::NoneError
。
当您的 Rust 应用程序增长时,它会经常发生,您必须返回一个可能包含不同类型错误的Result
。 在这种情况下,您通常定义自己的错误类型(枚举),它可以表示不同类型的错误。 然后对于每个可以包含的错误,您必须在自己的枚举上定义From
特征。 这可能是很多重复的工作,所以在quick-error
crate中有一个宏,可以帮助解决这个问题,并为每个可以包含的错误自动实现From
特征。
要编译代码,您可以定义以下错误枚举,它可以表示std::io::Error
以及std::option::NoneError
:
quick_error! {
#[derive(Debug)]
pub enum FrameError {
IoError(err: std::io::Error) {from() cause(err)}
MissingValue(err: std::option::NoneError) {from()}
}
}
而不是std::io::Result<Self>
您的from_bytes
function 然后必须返回使用您的新错误类型的std::result::Result
: Result<Self, FrameError>
。
完全组装,看起来像这样:
#![feature(try_trait)]
use quick_error::*;
quick_error! {
#[derive(Debug)]
pub enum FrameError {
IoError(err: std::io::Error) {from() cause(err)}
MissingValue(err: std::option::NoneError) {from()}
}
}
fn main() {
let emptyvec = Vec::new();
match Frame::from_bytes(&emptyvec) {
Err(_e) => {
println!("Received invalid frame");
}
Ok(_frame) => {
println!("Received valid frame");
}
}
}
struct Frame {
txflag: u8, // indicates if chunked
msgtype: u8, // a flag for message type
sender: u8, // which node ID sent this frame?
routeoffset: u8, // size of array of route for frame
route: Vec<u8>, // a list of node IDs that frame should pass
payload: Vec<u8>, // payload data
}
impl Frame {
/// parse from raw bytes
pub fn from_bytes(bytes: &Vec<u8>) -> Result<Self, FrameError> {
let txflag = bytes.get(0)?.clone();
let msgtype = bytes.get(1)?.clone();
let sender = bytes.get(2)?.clone();
let routesoffset = bytes.get(3)?.clone();
let routes = bytes.get(4..(4 + routesoffset as usize))?;
let (left, right) = bytes.split_at(2);
let data = Vec::from(right);
Ok(Frame {
txflag,
msgtype,
sender,
routeoffset: routesoffset,
route: Vec::from(routes),
payload: data,
})
}
}
要使用quick-error
箱,您必须将以下内容添加到您的Cargo.toml
:
[dependencies]
quick-error = "1.2.3"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.