前言:aliyun-oss-client 是我的第一个 rust 项目,随着版本的迭代,见证了笔者的 rust 水平的渐渐提高。这些版本里,从刚开始的,不会使用指针,导致产生了大量的copy,到后来逐渐的开始用指针,引用,智能指针等,节省了大量的内存开销,减少了大量的copy,笔者感觉有些是值得记录一下的。
今天想跟大家介绍的是将 aliyun 接口返回的数据,转化为任意的 rust 类型的通用方式,在做这个 lib 的之前的版本中,此 lib 只能将数据导入到 lib 内部的自有结构体中,随着笔者对 rust 了解的逐渐深入,发现了更加通用的的方式,将数据导出到其他开发者希望的类型,也是可行的。
因为 aliyun 接口返回的类型只能是 xml 格式,rust 在解析 xml 方面,并没有比较符合人体工程学的库,所以笔者在很早之前是自己手动解析 xml 的,oss-rs/traits.rs at master · tu6ge/oss-rs (github.com)
其实这块解析功能,完全可以开放出来,供大家使用,现在就将它的用法,介绍给大家:
use aliyun_oss_client::traits::{RefineObject, RefineObjectList};
use thiserror::Error;
struct MyFile {
key: String,
#[allow(dead_code)]
other: String,
}
impl RefineObject for MyFile {
type Error = MyError;
fn set_key(&mut self, key: &str) -> Result<(), Self::Error> {
self.key = key.to_string();
Ok(())
}
}
#[derive(Default)]
struct MyBucket {
name: String,
files: Vec<MyFile>,
}
impl RefineObjectList<MyFile> for MyBucket {
type Error = MyError;
fn set_name(&mut self, name: &str) -> Result<(), Self::Error> {
self.name = name.to_string();
Ok(())
}
fn set_list(&mut self, list: Vec<MyFile>) -> Result<(), Self::Error> {
self.files = list;
Ok(())
}
}
#[derive(Debug, Error)]
enum MyError {
#[error(transparent)]
QuickXml(#[from] quick_xml::Error),
}
fn get_with_xml() -> Result<(), MyError> {
// 这是阿里云接口返回的原始数据
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult>
<Name>foo_bucket</Name>
<Prefix></Prefix>
<MaxKeys>100</MaxKeys>
<Delimiter></Delimiter>
<IsTruncated>false</IsTruncated>
<NextContinuationToken>CiphcHBzL1RhdXJpIFB1Ymxpc2ggQXBwXzAuMS42X3g2NF9lbi1VUy5tc2kQAA--</NextContinuationToken>
<Contents>
<Key>9AB932LY.jpeg</Key>
<LastModified>2022-06-26T09:53:21.000Z</LastModified>
<ETag>"F75A15996D0857B16FA31A3B16624C26"</ETag>
<Type>Normal</Type>
<Size>18027</Size>
<StorageClass>Standard</StorageClass>
</Contents>
<KeyCount>3</KeyCount>
</ListBucketResult>"#;
// 除了设置Default 外,还可以做更多设置
let mut bucket = MyBucket::default();
// 利用闭包对 MyFile 做一下初始化设置
let init_file = || MyFile {
key: String::default(),
other: "abc".to_string(),
};
bucket.from_xml(xml, init_file)?;
assert!(bucket.name == "foo_bucket");
assert!(bucket.files[0].key == "9AB932LY.jpeg");
Ok(())
}
let res = get_with_xml();
if let Err(err) = res {
eprintln!("{}", err);
}