#tuple #proc-macro #traits #meta-programming #impl #for

fortuples

通过过程宏泛化元组上的固有和特质实现

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 过程宏

Download history 512/week @ 2024-03-14 272/week @ 2024-03-21 999/week @ 2024-03-28 497/week @ 2024-04-04 733/week @ 2024-04-11 1242/week @ 2024-04-18 155/week @ 2024-04-25 605/week @ 2024-05-02 567/week @ 2024-05-09 745/week @ 2024-05-16 581/week @ 2024-05-23 1419/week @ 2024-05-30 976/week @ 2024-06-06 1236/week @ 2024-06-13 301/week @ 2024-06-20 805/week @ 2024-06-27

每月 3,654 次下载
7 个crate中使用(通过 pallet-ismp

MIT 许可证

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