rust - 如何从文件或 URL 创建 Rust Quick XML 阅读器?

标签 rust

我有以下使用 quick_xml 库的代码:

use quick_xml::Reader;
use std::io::BufRead;
use std::path::Path;
use std::io::BufReader;

/// Returns an XML stream either from a file or a URL.
fn get_xml_stream(source: &str) -> Result<Reader<impl BufRead>, Error> {
    let local_path = Path::new(source);

    // Try to read a local file first.
    if local_path.is_file() {
        let reader =
            Reader::from_file(source).context(format!("couldn't read file {:?}", source))?;
        return Ok(reader);
    }
    // Try to fetch a remote file.
    let response = reqwest::get(source).context(format!(
        "File not found and failed fetching from remote URL {}",
        source
    ))?;
    if !response.status().is_success() {
        return Err(format_err!("XML download failed with {:#?}", response));
    }

    Ok(Reader::from_reader(BufReader::new(response)))
}

返回类型是动态的:读取器具有来自文件或响应正文的数据。

编译错误:
error[E0308]: mismatched types
   --> src/main.rs:225:43
    |
225 |     Ok(Reader::from_reader(BufReader::new(response)))
    |                                           ^^^^^^^^ expected struct `std::fs::File`, found struct `reqwest::response::Response`
    |
    = note: expected type `std::fs::File`
               found type `reqwest::response::Response`

编译器认为我们总是想从文件中读取,但这里是一个响应流。如何告诉编译器在 XML 阅读器中接受两种类型的缓冲阅读器?

最佳答案

返回 impl SomeTrait意味着该函数返回一种实现该特征的具体类型,而您只是不想说明它是什么类型。这并不意味着它可以返回异构类型。
Box<dyn BufRead>是正确的选择:

use failure::{Error, format_err, ResultExt};  // failure = "0.1.6"
use quick_xml::Reader;  // quick-xml = "0.17.2"
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;

/// Returns an XML stream either from a file or a URL.
fn get_xml_stream(source: &str) -> Result<Reader<Box<dyn BufRead>>, Error> {
    let local_path = Path::new(source);

    if local_path.is_file() {
        let file = File::open(local_path)?;
        let reader = BufReader::new(file);

        Ok(Reader::from_reader(Box::new(reader)))
    } else {
        let response = reqwest::get(source).context(format!(
            "File not found and failed fetching from remote URL {}",
            source
        ))?;
        if !response.status().is_success() {
            return Err(format_err!("XML download failed with {:#?}", response));
        }
        let reader = BufReader::new(response);

        Ok(Reader::from_reader(Box::new(reader)))
    }
}

作为旁注,混合本地路径和远程 URL 不是一个好主意。区区local_path.is_file()不足以净化输入。你已经被警告了。

关于rust - 如何从文件或 URL 创建 Rust Quick XML 阅读器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59456873/

相关文章:

c++ - 如何在 Rust 中编译和链接 .cpp 文件?

binary - 在 Rust 中读写 8 位有更好的方法吗?

concurrency - 互斥锁的 rust 访问选项

rust - 如何实现Into trait而不使用 `as usize`将所有输入转换为usize?

rust - 如何更改 Piston2D/PistonWindow/GlutinWindow 中的光标图标?

rust - 添加两个字符串时如何修复不匹配的类型?

shell - 如何在同时传送stdio的同时模拟TTY?

macros - 是否可以在具有单个实例化的 Rust 宏中多次使用参数?

enums - 在 crate 中时无法在范围内获取 Rust 枚举

rust - 如何实现 future 功能的流