5个不稳定版本
0.3.0 | 2022年1月17日 |
---|---|
0.2.1 | 2022年1月12日 |
0.2.0 | 2022年1月12日 |
0.1.1 | 2022年1月11日 |
0.1.0 | 2022年1月11日 |
#417 in 可视化
用于 newsly
19KB
152 行
Simple Tables 是一个易于创建表格结构的Rust库。这是通过宏来实现的。
目录
概述
创建表格
要创建表格,您可以使用宏 table_row
来表示行的结构,并使用 table
来将结构体用作表格。
示例
use simple_tables::macros::{table_row, table};
#[table_row]
struct MyTableRow {
id: u32,
name: String,
email: String,
address: String
}
#[table(rows = MyTableRow)]
struct MyTable {}
这些宏将分别实现 TableRow
和 Table
特性。您也可以手动实现它们。
函数
TableRow
和 Table
特性定义了一组函数,其中大部分具有默认实现。使用 table_row
和 table
宏将实现这些特性和相应的函数,针对您要针对的结构体。这些宏还提供了一些额外的函数。
ToString
这些宏还实现了表格的 ToString
特性,因此您可以使用 to_string
函数。
示例
use simple_tables::Table;
let rows: Vec<MyTableRow> = vec![
MyTableRow{ id: 0, name: "David Bowie".to_string(), email: "[email protected]".to_string(), address: "England".to_string()},
MyTableRow{ id: 1, name: "David Gilmour".to_string(), email: "[email protected]".to_string(), address: "England".to_string()},
MyTableRow{ id: 2, name: "Opeth".to_string(), email: "[email protected]".to_string(), address: "Sweden".to_string()},
MyTableRow{ id: 3, name: "The Beatles".to_string(), email: "[email protected]".to_string(), address: "England".to_string()}
];
let table = MyTable::from_vec(&rows);
let s = table.to_string();
println!("{}", s);
输出将如下
+----+---------------+-------------------+---------+
| id | name | email | address |
+====+===============+===================+=========+
| 0 | David Bowie | david@bowie.com | England |
+----+---------------+-------------------+---------+
| 1 | David Gilmour | david@gilmour.com | England |
+----+---------------+-------------------+---------+
| 2 | Opeth | info@opeth.com | Sweden |
+----+---------------+-------------------+---------+
| 3 | The Beatles | info@beatles.com | England |
+----+---------------+-------------------+---------+
创建新的表格实例
let empty_table = MyTable::new();
let populated_table = MyTable::from_vec(&vec);
获取行
您可以使用以下获取器之一获取行
table.get_rows()
table.get_rows_mut()
table.get_row_at(index)
获取列
您可以使用 get_column
函数获取列的所有值。此函数接受一个闭包来获取每个条目的值。
示例
#[table_row]
struct MyTableRow2 {
id: u32,
name: String
}
#[table(rows = TableRow)]
struct MyTable2 {}
let vec: Vec<MyTableRow2> = vec![
MyTableRow2{id: 1, name: String::from("Metallica")},
MyTableRow2{id: 2, name: String::from("Slipknot")}
];
let table2 = MyTable2::from_vec(&vec);
let ids: Vec<u32> = table2.get_column(|row| row.id); // The function takes in a closure
assert_eq!(vec![1,2], ids);
插入行
示例
let row = MyTableRow { id: 4, name: "Pink Floyd", email: "[email protected]", address: "England"};
// Appending the row to the end of the table
table.push(row);
// Inserting a row at the top of the table
table.insert_top(row);
// Inserting a row in the second position
table.insert(2, row);
行和列计数
您可以使用您表格上的 column_count()
函数来获取列的数量。您还可以使用 row_count()
获取行数。
具有UID的表格
我们可以指定具有唯一标识符的表格。以下示例展示了如何做到这一点
use simple_tables::IdTable;
#[table_row]
struct MyTableRow {
id: u32,
name: String
}
#[table(rows = MyTableRow)]
struct MyTable {}
// When you need a table with rows containing uid's, you will have to manually implement the
// `get_id_from_row` function
// The `IdTable` takes in 2 type parameters, one for the id's type and one for the rows's type
impl IdTable<u32, MyTableRow> for MyTable {
// This function will simply return the id field from the row
fn get_id_from_row(row: &MyTableRow) -> u32 {
row.id
}
}
注意:如果你的IDE抱怨说 the trait bound MyTable: Table<MyTableRow> is not satisfied
,你可以简单地忽略它。Table
特性在 table
宏中实现,但你的IDE只是不知道这一点。
要消除这些警告,你必须启用 org.rust.cargo.evaluate.build.scripts
和 org.rust.macros.proc
实验特性。在 IntelliJ 中,你可以通过按 ⇧⌘A
(macOs)或 ⌃⇧A
(Linux/Windows)并搜索 Experimental Features
来完成此操作,然后启用前面提到的两个特性。
根据UID获取行
你可以使用 get_row()
函数来获取与 uid 匹配的行。
示例
let vec = vec![
MyTableRow { id: 1, name: "Jimmy Page".to_string() },
MyTableRow { id: 2, name: "Slayer".to_string() },
MyTableRow { id: 3, name: "MGMT".to_string() }
];
let table = MyTable::from_vec(&vec);
let table_row = table.get_row(2).unwrap();
assert_eq!(vec[1], table_row.clone());
你还可以使用 get_row_mut(id)
方法以可变方式获取行。
示例
let vec = vec![
MyTableRow { id: 1, name: "Swedish House Mafia".to_string() },
MyTableRow { id: 2, name: "Pink Floyd".to_string() },
MyTableRow { id: 3, name: "Nick Cave & The Bad Seeds".to_string() }
];
let vec_unedited = vec![
MyTableRow { id: 1, name: "Swedish House Mafia".to_string() },
MyTableRow { id: 2, name: "Pink Floyd".to_string() },
MyTableRow { id: 3, name: "Nick Cave".to_string() }
];
let table = MyTable::from_vec(&vec);
let mut table2 = MyTable::from_vec(&vec_unedited);
let row = table2.get_row_mut(3).unwrap();
row.name = format!("{} {}", row.name, "& The Bad Seeds");
assert_eq!(table2.get_rows(), table.get_rows());
添加 derive 属性
你可以向你的表格添加 derive 属性,但你应该将它们放在 #[table]
之下。
示例
#[table(MyTableRow)
#[derive(PartialEq)]
struct MyTable {}
安装
只需将软件包添加到你的 cargo.toml
。
[dependencies]
simple_tables = "0.3.0"
你可以在 crates.io 上看到该软件包。
贡献
贡献和建议总是受欢迎的。
如果你知道如何改进这个软件包,请让我知道。
你还可以在问题选项卡中声明一个问题。
当你做出贡献时,请确保你的提交通过了测试。你可以通过进入 cd tables
目录并运行测试 cargo test
来运行测试。我还为这个存储库设置了 CircleCI,它将测试所有提交。如果你添加了新功能,请确保也为这个功能编写测试。
文档
文档可以在 这里 找到。
它也可以在 docs.rs 上找到,你也可以在这里找到以前版本的文档。
用例
这个项目开始是因为我在开发一个从 SQL 数据库检索数据的应用程序。在制作了我表格的调试表示之后,我想这可能是一个好主意,使其更通用,所以我开始着手这个软件包。
如果你感兴趣,这里有一个片段
use mysql::PooledConn;
use mysql::prelude::Queryable;
use simple_tables::{IdTable, Table};
use simple_tables::macros::*;
#[table_row]
pub struct DatabaseEntry {
id: u32,
name: String,
year: u32,
ban_id: u32,
ban: String,
emails: Emails
}
#[table(rows = DatabaseEntry)]
pub struct Database {}
impl IdTable<u32, DatabaseEntry> for Database {
fn get_id_from_row(row: &DatabaseEntry) -> u32 {
row.id
}
}
impl Database {
pub fn fetch(conn: &mut PooledConn) -> Database {
let mut database: Database = Database::new();
let query = "\
SELECT Users.User_Id as id, Users.Name as name, Years.Year_Id as year, Bannen.Ban_Id as ban_id, Bannen.Naam as ban, Emails.Email as email FROM Users \
INNER JOIN Years ON Users.Year_Id = Years.Year_Id \
INNER JOIN Bannen ON Years.Ban_Id = Bannen.Ban_Id \
LEFT JOIN Emails ON Emails.Email_Id = Users.User_Id\
";
conn.query_iter(query)
.unwrap()
.for_each(|row| {
let (user_id, name, years_id, ban_id, ban_naam, email):
(u32, String, u32, u32, String, Option<String>)
= mysql::from_row(row.unwrap());
if let Some(email) = email {
if let Some(entry) = database.get_row_mut(user_id) {
entry.emails.push(email);
} else {
// Create new entry
database.push(
DatabaseEntry {
id: user_id,
name,
year: years_id,
ban_id,
ban: ban_naam,
emails: Emails { emails: Some(vec![email]) }
}
);
}
} else {
// Create new entry
database.push(
DatabaseEntry {
id: user_id,
name,
year: years_id,
ban_id,
ban: ban_naam,
emails: if email.is_some() { Emails { emails: Some(vec![email.unwrap()]) } } else { Emails { emails: None } }
}
);
}
});
database
}
}
#[derive(Clone, Debug)]
pub struct Emails {
emails: Option<Vec<String>>
}
impl Emails {
fn push(&mut self, s: String) {
if let Some(ref mut v) = self.emails {
v.push(s);
}
}
}
impl ToString for Emails {
fn to_string(&self) -> String {
let mut s = String::new();
if self.emails.is_some() {
let len = self.emails.as_ref().unwrap().len();
for (i, email) in self.emails.as_ref().unwrap().iter().enumerate() {
if i != len - 1 {
s.push_str(format!("{}{}", email, ", ").as_str());
} else {
s.push_str(email);
}
}
} else {
s.push_str("None");
}
s
}
}
如果你用这个软件包构建了某些东西,请告诉我!
有问题?
请随意打开一个问题或直接与我联系。
许可
此软件包受 MIT 许可证 许可。详情请参阅 LICENSE 文件。
或者,此软件包还可以在 Apache 2.0 许可证 下许可。
依赖项
~1.5MB
~34K SLoC