6个版本
0.9.1 | 2023年10月25日 |
---|---|
0.9.0 | 2022年10月23日 |
0.2.0 | 2022年10月16日 |
0.1.2 | 2022年10月13日 |
#727 in 过程宏
每月 3,654 次下载
在 7 个crate中使用(通过 pallet-ismp)
195KB
6.5K SLoC
fortuples
泛化元组上的固有和特质实现的过程宏。
介绍
当需要为元组的组合实现特质或泛化类型时,Rust要求手动为每种元组类型提供单独的实现。
此crate提供了一个过程宏fortuples!
,用于编写类似于quote!
宏的代码模板。此宏将为每种元组类型展开提供的代码模板。
此外,一个属性宏#[auto_impl]
,它可以以完全自动化的方式为元组组合实现给定的特质。
此crate受到了impl_trait_for_tuples
的启发。
与impl_trait_for_tuples
的区别
您可以编写固有实现
struct Vector<T>(T);
fortuples! {
#[tuples::member_type(f32)]
#[tuples::min_size(2)]
#[tuples::max_size(3)]
#[tuples::tuple_name(Coords)]
impl Vector<#Coords> {
fn length(&self) -> f32 {
let coords = &self.0;
(#(#coords * #coords)+*).sqrt()
}
}
}
在实现体内部无需使用自定义关键字for_tuples!
相反,fortuples!
宏遵循类似于quote!
的语法,无需额外的标记。
trait Trait {
type Ret;
type Arg;
fn test(arg: Self::Arg) -> Self::Ret;
}
impl_trait_for_tuples
#[impl_for_tuples(5)]
impl Trait for Tuple {
for_tuples!( type Ret = ( #( Tuple::Ret ),* ); );
for_tuples!( type Arg = ( #( Tuple::Arg ),* ); );
fn test(arg: Self::Arg) -> Self::Ret {
for_tuples!( ( #( Tuple::test(arg.Tuple) ),* ) )
}
}
fortuples
fortuples! {
#[tuples::max_size(5)] // <-- optional, default = 16
impl Trait for #Tuple
where
#(#Member: Trait),*
{
type Ret = ( #(#Member::Ret),* );
type Arg = ( #(#Member::Arg),* );
fn test(arg: Self::Arg) -> Self::Ret {
( #(#Member::test(#arg)),* )
}
}
}
单独的属性宏,用于完整自动化的实现
impl_trait_for_tuples
#[impl_for_tuples(5)]
trait Notify {
fn notify(&self);
}
fortuples::auto_impl
#[fortuples::auto_impl]
#[tuples::max_size(5)] // <-- optional, default = 16
trait Notify {
fn notify(&self);
}
示例
fortuples!
过程宏
以下是fortuples!
使用的注释示例。
请参阅fortuples!
宏文档以了解宏设置(如#[tuples::min_size]
)。
trait Trait {
type Ret;
type Arg;
type FixedType;
const VALUE: i32;
const LENGTH: usize;
fn test_assoc_fn(arg: Self::Arg) -> Self::Ret;
fn test_self_fn(&self) -> Result<(), ()>;
}
fortuples! {
#[tuples::min_size(1)]
// +----- ^^^^^^^^^^^
// | The `fortuples!` macro will generate implementations starting with the empty tuple.
// |
// | Due to the `min_size` setting,
// | the implementations will start from the `(Member0,)` tuple.
impl Trait for #Tuple
// +----------- ^^^^^
// | a meta-variable that will expand to
// | `(Member0,)`, `(Member0, Member1)`, and so on.
where
#(#Member: Trait<FixedType = i32>),*
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// | A repetition -- the code inside the `#(...),*`
// | will expand as many times as many elements are in the current #Tuple.
// |
// | Inside the i-th code fragment, the #Member meta-variable will be substituted
// | by the i-th member type of the current #Tuple.
{
// The `Ret` type will be a tuple consisting of the `Ret` types
// from the current #Tuple member types
type Ret = (#(#Member::Ret),*);
// The `Arg` type will be a tuple consisting of the `Arg` types
// from the current #Tuple member types
type Arg = (#(#Member::Arg),*);
// The `VALUE` will be a sum of all `VALUE`s of the #Tuple member types.
const VALUE: i32 = #(#Member::VALUE)+*;
// +------------------------------- ^
// | Note that a `+` sign separates the `VALUE`s.
const LENGTH: usize = #len(Tuple);
// +----------------- ^^^^^^^^^^^
// | This expands to the current #Tuple length.
type FixedType = i32;
fn test_assoc_fn(arg: Self::Arg) -> Self::Ret {
( #(#Member::test_assoc_fn(#arg)),* )
// +----------------------- ^^^
// | Any identifier after the `#` sign that is neither
// | #Tuple, #Member, nor #len(Tuple)
// | is interpreted as a tuple variable.
// |
// | So the above code will expand like this:
// | ```
// | (
// | Member0::test_assoc_fn(arg.0),
// | Member1::test_assoc_fn(arg.1),
// | ...
// | MemberN::test_assoc_fn(arg.N),
// | )
// | ```
// | where `N` equals `#len(Tuple)`
}
fn test_self_fn(&self) -> Result<(), ()> {
#(#self.test_self_fn()?;)*
// +-------------------- ^
// | Note that there is no separator here.
Ok(())
}
}
}
显示不带注释的示例
fortuples!
过程宏(不带注释)
trait Trait {
type Ret;
type Arg;
type FixedType;
const VALUE: i32;
const LENGTH: usize;
fn test_assoc_fn(arg: Self::Arg) -> Self::Ret;
fn test_self_fn(&self) -> Result<(), ()>;
}
fortuples! {
#[tuples::min_size(1)]
impl Trait for #Tuple
where
#(#Member: Trait<FixedType = i32>),*
{
type Ret = (#(#Member::Ret),*);
type Arg = (#(#Member::Arg),*);
const VALUE: i32 = #(#Member::VALUE)+*;
const LENGTH: usize = #len(Tuple);
type FixedType = i32;
fn test_assoc_fn(arg: Self::Arg) -> Self::Ret {
( #(#Member::test_assoc_fn(#arg)),* )
}
fn test_self_fn(&self) -> Result<(), ()> {
#(#self.test_self_fn()?;)*
Ok(())
}
}
}
auto_impl
属性
可以使用auto_impl
属性以完全自动的方式实现特性。
此属性将自动为元组组合生成给定特性的实现。
有关属性设置和限制,请参阅auto_impl
的文档。
#[fortuples::auto_impl]
trait AutoImplTrait {
fn test(&self, a: i32, b: &f32);
}
依赖项
~1.5MB
~35K SLoC