作者:我是一颗菠菜 | 来源:互联网 | 2023-09-01 08:39
我对Rust还是很陌生,并且仍在尝试使用它。很酷,但是我显然不喜欢自己做的运动。作为参考,我使用的是rustc 1.39.0。
我想尝试编写一个简单的程序来从MSBuild的代码分析中读取XML,该代码输出了一些相当简单的XML。我认为的问题是,有一个元素( public static HttpClient getHttpClient()
{
if (_httpClient == null)
{
Uri baseUri = new Uri(Url.baseUrl);
if (baseUri.Scheme == "http")
{
var handler = new HttpClientHandler();
handler.ClientCertificateOptiOns= ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidatiOnCallback=
(httpRequestMessage,cert,cetChain,policyErrors) =>
{
return true;
};
_httpClient = new HttpClient(handler);
}
else
{
_httpClient = new HttpClient();
}
_httpClient.DefaultRequestHeaders.accept.Clear();
_httpClient.DefaultRequestHeaders.accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
_httpClient.BaseAddress = baseUri;
}
return _httpClient;
}
)通常为空,但有时可以在其下包含元素。更大的问题是我很讨厌Rust(而且我通常不处理XML),而且我不确定如何正确设置反序列化所需的结构。我正在使用Serde和quick_xml。当我将PATH
设置为String并使用在PATH下没有SFA元素的XML时,我的测试成功了。但是一旦我弄清楚该标签是如何被使用并相应地更新我的结构的,我就不断得到错误:
PATH
...即使测试XML文件中的 all 个缺陷在PATH下都具有SFA元素。
我正在处理的所有XML文件如下所示:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("missing field `FILEPATH`")',src\libcore\result.rs:1165:5
在许多情况下,
c:\projects\source\repos\defecttest\defecttest
source.cpp
8
5
26496
The variable 'y' is assigned only once,mark it as const (con.4).
main
main
6
c:\projects\source\repos\defecttest\defecttest
source.cpp
9
5
26496
The variable 'z' is assigned only once,mark it as const (con.4).
main
main
6
为空,但在某些情况下,它包含自己的PATH
元素:
SFA
在意识到这一点之前,DEFECT结构中的所有字段都设置为String。假设XML文件中的所有缺陷都没有在PATH下包含子元素,则可以正常工作。当我将其更改为SFA而不是String时,它给了我上面提到的缺少字段错误。我正在测试的代码示例:
main.rs
c:\projects\source\repos\defecttest\defecttest
source.cpp
9
5
26496
The variable 'z' is assigned only once,mark it as const (con.4).
main
main
6
c:\projects\source\repos\defecttest\defecttest
source.cpp
12
3
Cargo.toml
extern crate quick_xml;
extern crate serde;
use std::default::Default;
use std::env;
use std::vec::Vec;
use quick_xml::de::from_str;
use serde::{Serialize,Deserialize};
/*
* Structs for the defect XML
*/
#[derive(Serialize,Deserialize,Debug)]
#[allow(non_snake_case)]
pub struct DEFECTS {
#[serde(rename = "DEFECT",default)]
pub defects: Vec,}
#[derive(Default,Serialize,Debug)]
#[allow(non_snake_case)]
pub struct DEFECT {
#[serde(default)]
pub SFA: SFA,pub DEFECTCODE: String,pub DESCRIPTION: String,pub FUNCTION: String,pub DECORATED: String,pub FUNCLINE: String,#[serde(default)]
pub PATH: Vec,Debug)]
#[allow(non_snake_case)]
pub struct SFA {
pub FILEPATH: String,pub FILENAME: String,pub LINE: String,pub COLUMN: String,}
/*
* Main app code
*/
fn main() {
// Expect the path to the XML file to be passed as the first and only argument
let args: Vec = env::args().collect();
if args.len() != 2 {
panic!("Invalid argument count. Specify a single file to process.");
}
let processing_file = &args[1];
println!("Will attempt to process file: '{}'",&processing_file);
// Try to load the contents of the file
let file_content : String = match std::fs::read_to_string(&processing_file) {
Ok(file_content) => file_content,Err(e) => {
panic!("Failed to read file: '{}' -- {}",&processing_file,e);
}
};
// Now,try to deserialize the XML we have in file_content
let defect_list : DEFECTS = from_str(&file_content).unwrap();
// Assuming the unwrap above didn't blow up,we should get a count here
println!("Retrieved {} defects from file '{}'",defect_list.defects.len(),&processing_file);
}
示例输出
[package]
name = "rust_xml_test"
version = "0.1.0"
authors = ["fny82"]
edition = "2018"
[dependencies]
quick-xml = { version = "0.17",features = [ "serialize" ] }
serde = { version = "1.0",features = [ "derive" ] }
我确定自己做的事情很愚蠢,部分原因可能是我在挑战的范围和我目前对Rust的理解水平方面处于领先地位。谁能帮我弄清楚我的缺失和做错了什么?
有些相关:从那时起,我了解到可以使用C:\Development\RustXmlTest>cargo run -- "c:\development\rustxmltest\test3.xml"
Compiling rust_xml_test v0.1.0 (C:\Development\RustXmlTest)
Finished dev [unoptimized + debuginfo] target(s) in 1.56s
Running `target\debug\rust_xml_test.exe c:\development\rustxmltest\test3.xml`
Will attempt to process file: 'c:\development\rustxmltest\test3.xml'
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("missing field `FILEPATH`")',src\libcore\result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
error: process didn't exit successfully: `target\debug\rust_xml_test.exe c:\development\rustxmltest\test3.xml` (exit code: 101)
属性来使我的结构符合Rust的命名约定,但是到目前为止,直到我了解了这一点,我才不想再搞砸了基础功能正常工作。
----编辑----
供参考,通过@edwardw的更正,现在可以运行的代码:
rename
示例:
extern crate quick_xml;
extern crate serde;
use std::default::Default;
use std::env;
use std::vec::Vec;
use quick_xml::de::from_str;
use serde::{Serialize,pub PATH: PATH,Debug)]
#[allow(non_snake_case)]
pub struct PATH {
pub SFA: Option,&processing_file);
}
其中test1.xml包含:
C:\Development\RustXmlTest>cargo run -- "c:\development\rustxmltest\test1.xml"
Compiling rust_xml_test v0.1.0 (C:\Development\RustXmlTest)
Finished dev [unoptimized + debuginfo] target(s) in 1.66s
Running `target\debug\rust_xml_test.exe c:\development\rustxmltest\test1.xml`
Will attempt to process file: 'c:\development\rustxmltest\test1.xml'
Retrieved 2 defects from file 'c:\development\rustxmltest\test1.xml'
PATH
本身应建模为具有一个可选字段的结构。这有效:
#[derive(Default,Serialize,Deserialize,Debug)]
#[allow(non_snake_case)]
pub struct DEFECT {
#[serde(default)]
pub SFA: SFA,pub DEFECTCODE: String,pub DESCRIPTION: String,pub FUNCTION: String,pub DECORATED: String,pub FUNCLINE: String,pub PATH: PATH,}
#[derive(Default,Debug)]
#[allow(non_snake_case)]
pub struct PATH {
SFA: Option,}