Rust中无法从Peekable的Result移出io::Error,如何将IO错误传播到自定义错误类型?
解决Rust中IO错误包装的移动问题
嘿,我知道你卡在这了!咱们来理清楚问题出在哪,然后搞定它~
你遇到的E0507错误,核心原因是**peek()返回的是共享引用**:Peekable的peek()方法给出的是Option<&Result<u8, std::io::Error>>——也就是说,当你匹配到Some(Err(e))时,e是一个&std::io::Error类型的引用,而不是拥有所有权的std::io::Error实例。因为std::io::Error没有实现Copy trait,所以你没办法直接通过*e把它从引用后面“挪”出来。
你之前尝试用clone的思路完全正确,只是用法需要微调。因为std::io::Error已经实现了Clone trait,直接调用e.clone()就能得到一个拥有所有权的std::io::Error实例,刚好可以放进你的MyError::IO变体里。
修正后的基础版本代码
use std::io::{self, Read}; use std::iter::Peekable; enum MyError { EOF, IO(std::io::Error), } fn peek_byte<R>(mut p: Peekable<io::Bytes<R>>) -> Result<u8, MyError> where R: Read, { match p.peek() { None => Err(MyError::EOF), Some(Err(e)) => Err(MyError::IO(e.clone())), // 这里改用e.clone() Some(Ok(byte)) => Ok(*byte), } }
更简洁的链式调用版本
如果你想更符合Rust的函数式风格,也可以用Result和Option的链式方法来替代手动match,代码会更紧凑:
use std::io::{self, Read}; use std::iter::Peekable; enum MyError { EOF, IO(std::io::Error), } fn peek_byte<R>(mut p: Peekable<io::Bytes<R>>) -> Result<u8, MyError> where R: Read, { p.peek() .ok_or(MyError::EOF) // 将None转为MyError::EOF .and_then(|result| { // 把内部的&Result转换成拥有所有权的Result,同时包装错误 result.map_err(MyError::IO).cloned() }) }
这里的cloned()会把&u8转换成u8(因为u8实现了Clone),而map_err(MyError::IO)直接把std::io::Error包装成你的自定义错误类型,一步到位。
内容的提问来源于stack exchange,提问作者George Madrid
相关产品推荐
相关产品推荐

