{"id":33927140,"url":"https://github.com/mrshiposha/fortuples","last_synced_at":"2025-12-12T10:45:49.587Z","repository":{"id":61373748,"uuid":"549979158","full_name":"mrshiposha/fortuples","owner":"mrshiposha","description":"Procedural macros to generalize inherent and trait implementations over tuples","archived":false,"fork":false,"pushed_at":"2023-10-25T22:35:51.000Z","size":115,"stargazers_count":4,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-21T17:26:37.383Z","etag":null,"topics":["crate","for","generalization","impl","macro","macros","metaprogramming","proc-macro","rust","trait","tuple","tuples"],"latest_commit_sha":null,"homepage":"https://docs.rs/fortuples/latest/fortuples/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mrshiposha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-10-12T02:51:55.000Z","updated_at":"2025-01-08T05:42:49.000Z","dependencies_parsed_at":"2023-11-20T05:04:17.731Z","dependency_job_id":"f1aa6851-4925-47db-b26f-913bce9352ba","html_url":"https://github.com/mrshiposha/fortuples","commit_stats":{"total_commits":60,"total_committers":2,"mean_commits":30.0,"dds":0.01666666666666672,"last_synced_commit":"95525dbf6ba2a96cd6acf75db46c4cf2d5a047c4"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mrshiposha/fortuples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrshiposha%2Ffortuples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrshiposha%2Ffortuples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrshiposha%2Ffortuples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrshiposha%2Ffortuples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrshiposha","download_url":"https://codeload.github.com/mrshiposha/fortuples/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrshiposha%2Ffortuples/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27681234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-12T02:00:06.775Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crate","for","generalization","impl","macro","macros","metaprogramming","proc-macro","rust","trait","tuple","tuples"],"created_at":"2025-12-12T10:45:42.254Z","updated_at":"2025-12-12T10:45:49.578Z","avatar_url":"https://github.com/mrshiposha.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fortuples\n[![](https://docs.rs/fortuples/badge.svg)](https://docs.rs/fortuples/) [![](https://img.shields.io/crates/v/fortuples.svg)](https://crates.io/crates/fortuples) [![](https://img.shields.io/crates/d/fortuples.svg)](https://crates.io/crates/fortuples)\n\nProcedural macros to generalize inherent and trait implementations over tuples.\n\n* [Introduction](#introduction)\n* [Differences from `impl_trait_for_tuples`](#differences-from-impl_trait_for_tuples)\n* [Examples](#examples)\n\n## Introduction\n\nWhen it is a need to implement either a trait or a generalized type for a combination of tuples,\nRust requires separate implementations to be provided for each tuple variety manually.\n\nThis crate provides a proc-macro `fortuples!` to write code templates similar to the [`quote!`](https://github.com/dtolnay/quote) macro.\nThis macro will expand the provided code template for each tuple variety.\n\nAlso, an attribute macro `#[auto_impl]` that implements a given trait for tuple combinations in a completely automatic way.\n\n_This crate is inspired by the [`impl_trait_for_tuples`](https://github.com/bkchr/impl-trait-for-tuples)._\n\n----\n\n## Differences from `impl_trait_for_tuples`\n\n##### You can write inherent implementations\n```rust\nstruct Vector\u003cT\u003e(T);\n\nfortuples! {\n    #[tuples::member_type(f32)]\n    #[tuples::min_size(2)]\n    #[tuples::max_size(3)]\n    #[tuples::tuple_name(Coords)]\n    impl Vector\u003c#Coords\u003e {\n        fn length(\u0026self) -\u003e f32 {\n            let coords = \u0026self.0;\n\n            (#(#coords * #coords)+*).sqrt()\n        }\n    }\n}\n```\n\n----\n\n##### You don't need to use a custom keyword `for_tuples!` inside the implementation body\n\nInstead, the `fortuples!` macro follows the [`quote!`](https://github.com/dtolnay/quote)-like syntax without extra tokens.\n\n```rust\ntrait Trait {\n    type Ret;\n    type Arg;\n\n    fn test(arg: Self::Arg) -\u003e Self::Ret;\n}\n```\n\n###### impl_trait_for_tuples\n\n```rust\n#[impl_for_tuples(5)]\nimpl Trait for Tuple {\n    for_tuples!( type Ret = ( #( Tuple::Ret ),* ); );\n    for_tuples!( type Arg = ( #( Tuple::Arg ),* ); );\n\n    fn test(arg: Self::Arg) -\u003e Self::Ret {\n        for_tuples!( ( #( Tuple::test(arg.Tuple) ),* ) )\n    }\n}\n```\n\n###### fortuples\n\n```rust\nfortuples! {\n    #[tuples::max_size(5)] // \u003c-- optional, default = 16\n    impl Trait for #Tuple\n    where\n        #(#Member: Trait),*\n    {\n        type Ret = ( #(#Member::Ret),* );\n        type Arg = ( #(#Member::Arg),* );\n\n        fn test(arg: Self::Arg) -\u003e Self::Ret {\n            ( #(#Member::test(#arg)),* )\n        }\n    }\n}\n```\n\n----\n\n##### Separate attribute macro for full-automatic implementation\n\n###### impl_trait_for_tuples\n\n```rust\n#[impl_for_tuples(5)]\ntrait Notify {\n    fn notify(\u0026self);\n}\n```\n\n###### fortuples::auto_impl\n\n```rust\n#[fortuples::auto_impl]\n#[tuples::max_size(5)] // \u003c-- optional, default = 16\ntrait Notify {\n    fn notify(\u0026self);\n}\n```\n\n----\n\n## Examples\n\n#### `fortuples!` proc-macro\n\nHere is commented example of `fortuples!` usage.\n\n_See the [`fortuples!`](https://docs.rs/fortuples/latest/fortuples/macro.fortuples.html) macro documentation to learn about the macro settings (like `#[tuples::min_size]`)._\n\n```rust\ntrait Trait {\n    type Ret;\n\n    type Arg;\n\n    type FixedType;\n\n    const VALUE: i32;\n\n    const LENGTH: usize;\n\n    fn test_assoc_fn(arg: Self::Arg) -\u003e Self::Ret;\n\n    fn test_self_fn(\u0026self) -\u003e Result\u003c(), ()\u003e;\n}\n\nfortuples! {\n    #[tuples::min_size(1)]\n    // +----- ^^^^^^^^^^^\n    // | The `fortuples!` macro will generate implementations starting with the empty tuple.\n    // |\n    // | Due to the `min_size` setting,\n    // | the implementations will start from the `(Member0,)` tuple.\n\n    impl Trait for #Tuple\n    // +----------- ^^^^^\n    // | a meta-variable that will expand to\n    // | `(Member0,)`, `(Member0, Member1)`, and so on.\n\n    where\n        #(#Member: Trait\u003cFixedType = i32\u003e),*\n    //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // | A repetition -- the code inside the `#(...),*`\n    // | will expand as many times as many elements are in the current #Tuple.\n    // |\n    // | Inside the i-th code fragment, the #Member meta-variable will be substituted\n    // | by the i-th member type of the current #Tuple.\n    {\n        // The `Ret` type will be a tuple consisting of the `Ret` types\n        // from the current #Tuple member types\n        type Ret = (#(#Member::Ret),*);\n\n        // The `Arg` type will be a tuple consisting of the `Arg` types\n        // from the current #Tuple member types\n        type Arg = (#(#Member::Arg),*);\n\n        // The `VALUE` will be a sum of all `VALUE`s of the #Tuple member types.\n        const VALUE: i32 = #(#Member::VALUE)+*;\n        // +------------------------------- ^\n        // | Note that a `+` sign separates the `VALUE`s.\n\n        const LENGTH: usize = #len(Tuple);\n        // +----------------- ^^^^^^^^^^^\n        // | This expands to the current #Tuple length.\n\n        type FixedType = i32;\n\n        fn test_assoc_fn(arg: Self::Arg) -\u003e Self::Ret {\n            ( #(#Member::test_assoc_fn(#arg)),* )\n            // +----------------------- ^^^\n            // | Any identifier after the `#` sign that is neither\n            // | #Tuple, #Member, nor #len(Tuple)\n            // | is interpreted as a tuple variable.\n            // |\n            // | So the above code will expand like this:\n            // | ```\n            // |    (\n            // |        Member0::test_assoc_fn(arg.0),\n            // |        Member1::test_assoc_fn(arg.1),\n            // |        ...\n            // |        MemberN::test_assoc_fn(arg.N),\n            // |    )\n            // | ```\n            // | where `N` equals `#len(Tuple)`\n        }\n\n        fn test_self_fn(\u0026self) -\u003e Result\u003c(), ()\u003e {\n            #(#self.test_self_fn()?;)*\n            // +-------------------- ^\n            // | Note that there is no separator here.\n\n            Ok(())\n        }\n    }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eShow the example without comments\u003c/summary\u003e\n\n#### `fortuples!` proc-macro (without comments)\n\n```rust\ntrait Trait {\n    type Ret;\n\n    type Arg;\n\n    type FixedType;\n\n    const VALUE: i32;\n\n    const LENGTH: usize;\n\n    fn test_assoc_fn(arg: Self::Arg) -\u003e Self::Ret;\n\n    fn test_self_fn(\u0026self) -\u003e Result\u003c(), ()\u003e;\n}\n\nfortuples! {\n    #[tuples::min_size(1)]\n    impl Trait for #Tuple\n    where\n        #(#Member: Trait\u003cFixedType = i32\u003e),*\n    {\n        type Ret = (#(#Member::Ret),*);\n\n        type Arg = (#(#Member::Arg),*);\n\n        const VALUE: i32 = #(#Member::VALUE)+*;\n\n        const LENGTH: usize = #len(Tuple);\n\n        type FixedType = i32;\n\n        fn test_assoc_fn(arg: Self::Arg) -\u003e Self::Ret {\n            ( #(#Member::test_assoc_fn(#arg)),* )\n        }\n\n        fn test_self_fn(\u0026self) -\u003e Result\u003c(), ()\u003e {\n            #(#self.test_self_fn()?;)*\n\n            Ok(())\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n\n#### `auto_impl` attribute\n\nThere is an option to implement a trait\nin a completely automatic way using the `auto_impl` attribute.\n\nThis attribute will automatically generate implementations of the given trait\nfor tuple combinations.\n\n_See the [`auto_impl`](https://docs.rs/fortuples/latest/fortuples/attr.auto_impl.html) documentation to learn about the\nattribute's settings and limitations._\n\n```rust\n#[fortuples::auto_impl]\ntrait AutoImplTrait {\n    fn test(\u0026self, a: i32, b: \u0026f32);\n}\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrshiposha%2Ffortuples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrshiposha%2Ffortuples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrshiposha%2Ffortuples/lists"}