国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【社區(qū)投稿】給Rust的Struct自動(dòng)實(shí)現(xiàn)trait

這篇具有很好參考價(jià)值的文章主要介紹了【社區(qū)投稿】給Rust的Struct自動(dòng)實(shí)現(xiàn)trait。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

給Rust的Struct自動(dòng)實(shí)現(xiàn)trait

我們通常使用

#[derive(Clone,?Debug)]

這樣的方式給struct自動(dòng)實(shí)現(xiàn)相應(yīng)的trait,從而讓struct具備某些特性,但是如果我們想讓編譯器給struct自動(dòng)實(shí)現(xiàn)自己定義的trait要怎么辦?

首先我們需要有一個(gè)trait,假設(shè)如下面的定義:

pub?trait?Printable?{
????pub?fn?print_me(&self);
}

我們定義這個(gè)trait給struct賦予一個(gè)行為是逐行打印struct的所有Field。當(dāng)然如果是自己實(shí)現(xiàn)肯定是可以憑空亂寫的,那么我們可以和Debug一樣,在 derive 中讓編譯器自動(dòng)添加默認(rèn)的實(shí)現(xiàn)。

首先需要給crate添加一個(gè)子crate:

cargo?new?--lib?printable

然后在當(dāng)前crate的 Cargo.toml 中添加依賴

[workspace]
members?=?[
????".",
????"printable"
]
[dependencies]
printable?=?{?version?=?"*",?path?=?"printable"}

在printable 的 Cargo.toml 里還需要添加依賴

[dependencies]
syn?=?{?version?=?"1.0",?features?=?["full"]?}
quote?=?"1.0"
proc-macro2?=?"1.0.51"

我們需要這三個(gè)crate來簡化代碼生成的工作,這里proc-macro2提供了自動(dòng)實(shí)現(xiàn)宏的功能,syn用來解析結(jié)構(gòu)體,quote用來輸出TokenStream。

在 printable 的lib.rs 文件中

#[proc_macro_derive(Printable)]
pub?fn?print_info_derive(input:?TokenStream)?->?TokenStream?{
}

我們?cè)诤瘮?shù) print_info_derive 中輸出的TokenStream,就會(huì)在編譯時(shí)動(dòng)態(tài)注入到struct中,這里參數(shù)input就是struct本身的代碼流。

我們通過解析input就可以分析出 Struct的名字,F(xiàn)ield列表,所有Field的名字,類型…..

下面是簡化后的代碼:

#[proc_macro_derive(Printable)]
pub?fn?print_info_derive(input:?TokenStream)?->?TokenStream?{
????let?struct_name?=?to_snake_case(input.ident.to_string().as_str());
????????
????let?fields?=?match?input.data.clone()?{
????????syn::Data::Struct(data)?=>?data.fields,
????????_?=>?panic!("Only?structs?are?supported"),
????};
????let?fields_name:?Vec<Ident>?=?fields.iter().map(|field|?{
????????field.ident.as_ref().unwrap().clone()
????}).collect();
}

之后我們就需要構(gòu)建輸出的代碼流,這里使用 quote! 這個(gè)宏來實(shí)現(xiàn)。

#[proc_macro_derive(Printable)]
pub?fn?print_info_derive(input:?TokenStream)?->?TokenStream?{
????let?struct_name?=?to_snake_case(input.ident.to_string().as_str());
????????
????let?fields?=?match?input.data.clone()?{
????????syn::Data::Struct(data)?=>?data.fields,
????????_?=>?panic!("Only?structs?are?supported"),
????};
????let?fields_name:?Vec<Ident>?=?fields.iter().map(|field|?{
????????field.ident.as_ref().unwrap().clone()
????}).collect();
????let?output_token?=?quote!?{
????????impl?Printable?for?#struct_name?{
????????????pub?fn?print_me(&self)?{
????????????????//這里添加逐行打印Field的代碼,因?yàn)閝uote里本來就是在輸出代碼流
????????????????//所以不能直接訪問fields_name,比如循環(huán)之類的,所以我們這里需要
????????????????//把生成這部分代碼提取到函數(shù)外
????????????}
????????}
????}
????output_token.into()
}

為了簡單演示我們就使用一個(gè)函數(shù)來實(shí)現(xiàn):

fn?gen_print(fileds:?Vec<Ident>)?->?TokenStream2?{
????let?print_stmts?=fields.iter().map(|field|?{
????????quote!?{
????????????println!("field:{}",?&self.#field);
????????}
????});
????quote!{
????????#(#print_stmts)*
????}
}

最后組裝一下,lib.rs ?的代碼如下:

#[proc_macro_derive(Printable)]
pub?fn?print_info_derive(input:?TokenStream)?->?TokenStream?{
????let?struct_name?=?to_snake_case(input.ident.to_string().as_str());
????????
????let?fields?=?match?input.data.clone()?{
????????syn::Data::Struct(data)?=>?data.fields,
????????_?=>?panic!("Only?structs?are?supported"),
????};
????let?fields_name:?Vec<Ident>?=?fields.iter().map(|field|?{
????????field.ident.as_ref().unwrap().clone()
????}).collect();
????let?print_code?=?gen_print(fields_name);
????let?output_token?=?quote!?{
????????impl?Printable?for?#struct_name?{
????????????pub?fn?print_me(&self)?{
????????????????#output_token
????????????}
????????}
????}
????output_token.into()
}

如此這般一通操作后,我們隨便一定一個(gè)Struct:

#[derive(Debug,?Printable)]
struct?TestTb?{
????id:?String,
????name:?String,
????ts:?i32
}

就可以

TestTb{id:?"123".to_string(),?name:?"alex",?ts:?111}.print_me();

就可以逐行打印出所有的Field了。

那么靈活的使用這個(gè)玩法,我們可以根據(jù)Struct的Field,自動(dòng)生成 insert, update, delete的SQL也是可以的。給每個(gè)Field自動(dòng)生成getter,setter方法…… (這個(gè)Java味太濃了,だめ)

研究這個(gè)是為了給 sqlx 增加一個(gè)自動(dòng)生成insert,update,delete方法的增強(qiáng),因?yàn)椴幌矚g寫超長的insert和update語句。

Amusez-vous tous!文章來源地址http://www.zghlxwxcb.cn/news/detail-828716.html

到了這里,關(guān)于【社區(qū)投稿】給Rust的Struct自動(dòng)實(shí)現(xiàn)trait的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Rust 基礎(chǔ)篇】Rust Sized Trait:理解Sized Trait與動(dòng)態(tài)大小類型

    Rust是一門以安全性和性能著稱的系統(tǒng)級(jí)編程語言。在Rust中,類型大小的確定在編譯期是非常重要的。然而,有些類型的大小在編譯期是無法確定的,這就涉及到了Rust中的動(dòng)態(tài)大小類型(DST)。為了保證在編譯期可以確定類型的大小,Rust引入了Sized trait。本篇博客將深入探討

    2024年02月14日
    瀏覽(20)
  • 【Rust 基礎(chǔ)篇】Rust Deref Trait 的使用

    在 Rust 中,Deref trait 是一種特殊的 trait,用于重載解引用操作符 * 。通過實(shí)現(xiàn) Deref trait,我們可以定義類型的解引用行為,使其在使用 * 運(yùn)算符時(shí)表現(xiàn)得像引用類型。 本篇博客將詳細(xì)介紹 Rust 中如何實(shí)現(xiàn)和使用 Deref trait,以及它在代碼中的應(yīng)用場(chǎng)景。 Deref trait 的定義如下:

    2024年02月17日
    瀏覽(30)
  • 研讀Rust圣經(jīng)解析——Rust learn-16(高級(jí)trait,宏)

    研讀Rust圣經(jīng)解析——Rust learn-16(高級(jí)trait,宏)

    我們使用type即可聲明一個(gè)關(guān)聯(lián)類型,關(guān)聯(lián)類型的作用就是簡化和隱藏顯示類型(個(gè)人認(rèn)為) 簡化:一個(gè)很長的類型總是被需要時(shí),需要開發(fā)者耗費(fèi)精力的重復(fù)書寫,而且若有改動(dòng),則需要改多個(gè)地方 隱藏:對(duì)外部調(diào)用者隱藏,外部調(diào)用者無需知道它指的是什么,只要

    2024年02月02日
    瀏覽(18)
  • Rust-trait

    Rust-trait

    Rust語言中的trait是非常重要的概念。 在Rust中,trait這一個(gè)概念承擔(dān)了多種職責(zé)。在中文里,trait可以翻譯為“特征”“特點(diǎn)”“特性”等。 trait中可以定義函數(shù)。用例子來說明,我們定義如下的trait: 上面這個(gè)trait包含了一個(gè)方法,這個(gè)方法只有一個(gè)參數(shù),這個(gè)self參數(shù)是什么意

    2024年01月20日
    瀏覽(38)
  • rust學(xué)習(xí)-泛型和trait

    Option,Vec,HashMapK, V,ResultT, E等,取函數(shù)以減少代碼重復(fù)的機(jī)制 兩個(gè)函數(shù),不同點(diǎn)只是名稱和簽名類型 重寫如下 為所有類型的結(jié)構(gòu)體提供方法 只為f32提供方法 方法使用了與結(jié)構(gòu)體定義中不同類型的泛型 Rust 實(shí)現(xiàn)了泛型,使得使用泛型類型參數(shù)的代碼相比使用具體類型并沒

    2024年02月17日
    瀏覽(15)
  • Rust語法: 枚舉,泛型,trait

    這是我學(xué)習(xí)Rust的筆記,本文適合于有一定高級(jí)語言基礎(chǔ)的開發(fā)者看不適合剛?cè)腴T編程的人,對(duì)于一些概念像枚舉,泛型等,不會(huì)再做解釋,只寫在Rust中怎么用。 枚舉的定義與賦值 枚舉的定義格式如下: enum 枚舉名{ 值1(附加類型), 值2(附加類型),… } 其中,關(guān)聯(lián)類型可以省去

    2024年02月13日
    瀏覽(23)
  • 30天拿下Rust之Trait

    概述 ????????在Rust中,Trait是一個(gè)核心概念,它允許我們定義類型應(yīng)該具有的行為。Trait類似于其他語言中的接口,但Rust的Trait更為強(qiáng)大和靈活。它不僅定義了一組方法,還允許我們指定方法的默認(rèn)實(shí)現(xiàn)、泛型約束和繼承。通過Trait,我們可以定義一組方法的簽名和關(guān)聯(lián)類

    2024年03月17日
    瀏覽(23)
  • Rust之泛型、trait與生命周期

    泛型是具體類型或其他屬性的抽象替代。在編寫代碼時(shí),可以直接描述泛型的行為,或者它與其他泛型產(chǎn)生的聯(lián)系,而無須知曉它在編譯和運(yùn)行代碼時(shí)采用的具體類型。 們可以在聲明函數(shù)簽名或結(jié)構(gòu)體等元素時(shí)使用泛型,并在隨后搭配不同的具體類型來使用這些元素。 當(dāng)使

    2024年02月13日
    瀏覽(25)
  • Rust系列(四) trait備忘錄(持續(xù)更新)

    上一篇:Rust系列(三) 類型系統(tǒng)與trait 基于官方文檔進(jìn)行簡單學(xué)習(xí)記錄,保證所有示例是可運(yùn)行的基本單元。測(cè)試 rust 程序除了使用官方的 playground 之外,還可以通過定義 [[example]] 來運(yùn)行程序。 用于 不可變對(duì)象 的解引用操作,語法類似 *v 。 官方文檔: https://doc.rust-lang.org

    2024年02月14日
    瀏覽(22)
  • 【Rust筆記】意譯解構(gòu) Object Safety for trait

    【Rust筆記】意譯解構(gòu) Object Safety for trait

    借助【虛表 vtable 】對(duì)被調(diào)用成員函數(shù)【運(yùn)行時(shí)·內(nèi)存尋址】的作法允許系統(tǒng)編程語言 Rust 模仿出 OOP 高級(jí)計(jì)算機(jī)語言才具備的【專用·多態(tài) Ad-hoc Polymorphism 】特性。 計(jì)算機(jī)高級(jí)語言中的“多態(tài)”術(shù)語是一個(gè)泛指。它通常可被細(xì)化為 基于繼承關(guān)系的“ 子類 ·多態(tài)”? Subtype Po

    2024年02月15日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包