{"id":22122088,"url":"https://github.com/dekirisu/intuple","last_synced_at":"2025-10-13T07:11:41.719Z","repository":{"id":60159199,"uuid":"541331153","full_name":"dekirisu/intuple","owner":"dekirisu","description":"Convert structs/enums into/from tuples - recursive, ignore fields","archived":false,"fork":false,"pushed_at":"2025-05-30T16:54:41.000Z","size":39,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-01T12:19:56.804Z","etag":null,"topics":["conversion","convert","ignore","recursive","rust","rust-crate","rust-lang","rust-library","struct","structure","tuple","tuples"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dekirisu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-25T22:50:24.000Z","updated_at":"2025-06-04T11:59:43.000Z","dependencies_parsed_at":"2024-12-01T15:17:22.827Z","dependency_job_id":"053fc724-aad6-4db8-a4a8-da92a70577c6","html_url":"https://github.com/dekirisu/intuple","commit_stats":{"total_commits":11,"total_committers":1,"mean_commits":11.0,"dds":0.0,"last_synced_commit":"8d3e3cfe18025a16c134d283af23b1c8c196be06"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dekirisu/intuple","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dekirisu%2Fintuple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dekirisu%2Fintuple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dekirisu%2Fintuple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dekirisu%2Fintuple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dekirisu","download_url":"https://codeload.github.com/dekirisu/intuple/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dekirisu%2Fintuple/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268057253,"owners_count":24188618,"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-07-31T02:00:08.723Z","response_time":66,"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":["conversion","convert","ignore","recursive","rust","rust-crate","rust-lang","rust-library","struct","structure","tuple","tuples"],"created_at":"2024-12-01T15:17:19.350Z","updated_at":"2025-09-20T02:46:07.766Z","avatar_url":"https://github.com/dekirisu.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/78398528/282761791-a98ce5c2-2e51-4edb-8652-f89325192726.gif\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/dekirisu/intuple\" style=\"position:relative\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/github-dekirisu/intuple-ee6677\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://crates.io/crates/intuple\" style=\"position:relative\"\u003e\n        \u003cimg src=\"https://img.shields.io/crates/v/intuple\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://discord.gg/kevWvBuPFg\" style=\"position:relative\"\u003e\n        \u003cimg src=\"https://img.shields.io/discord/515100001903312898\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n## Features\n🐍 convert a **struct** into a tuple and back\u003cbr\u003e\n🦎 convert an **enum** into a tuple and back\u003cbr\u003e\n🦢 get a tuple of (mut) references of fields of a **struct**\u003cbr\u003e\n🐓 get a tuple of (mut) references of fields of an **enum**\u003cbr\u003e\n🦥 ignore specific fields\u003cbr\u003e\n🦆 do it all recursively\n## Usage\n🐠 add **intuple** to the dependencies in the `Cargo.toml`:\n```toml\n[dependencies]\nintuple = \"0.2\"\n```\n🦀 use/import everything into rust:\n```rust \nuse intuple::*;\n```\n🦚 multiple ways to convert:\n```rust \n#[derive(Intuple)]\nstruct Struct {a:u32, b:u32, c:u32}\n\nfn main(){\n    // use std traits\n    let strct: Struct = (3,2,1).into();\n    let tuple = \u003c(u32, u32, u32)\u003e::from(strct);\n    let strct = Struct::from((3,2,1));\n    let tuple: (u32, u32, u32) = strct.into();\n    // OR intuple trait\n    let strct = Struct::from_tuple((3,2,1));\n    let tuple = strct.into_tuple(); // or strct.intuple()\n    // references\n    let strct = Struct::from_tuple((3,2,1));    \n    let tupref = strct.as_tuple_ref(); // (\u0026u32,\u0026u32,\u0026u32)\n    let tupref = strct.as_tuple_ref_mut(); // (\u0026mut u32,\u0026mut u32,\u0026mut u32)\n    *tupref.1 = 3;\n}\n```\n## Tuple Type\n🦊 access the resulting tuple types through a qualified path:\n```rust \n#[derive(Intuple)]\nstruct Nice {a:u32, b:u32, c:u32}\nfn main(){\n    let tup: \u003cNice as Intuple\u003e::Tuple = (3,2,1);\n    let tup: (u32, u32, u32) = (3,2,1); // \u003c- same as above\n    // reference tuple types\n    let tup: \u003cNice as IntupleRef\u003e::Tuple = (\u00263,\u00262,\u00261);\n    let tup: (\u0026u32, \u0026u32, \u0026u32) = (\u00263,\u00262,\u00261); // \u003c- same as above\n    // mut reference tuple types\n    let tup: \u003cNice as IntupleRef\u003e::TupleMut = (\u0026mut 3,\u0026mut 2,\u0026mut 1);\n    let tup: (\u0026mut u32, \u0026mut u32, \u0026mut u32) = (\u0026mut 3,\u0026mut 2,\u0026mut 1); // \u003c- same as above\n}\n```\n## Ignoring\n🦥 ignore specific fields with `#[igno]`/`#[ignore]`\u003cbr\u003e\n🐻 or `#[intuple(igno)]`/`#[intuple(ignore)]`\u003cbr\u003e\n🐼 ignored fields need to implement [Default](https://doc.rust-lang.org/std/default/trait.Default.html) while converting to a struct\n```rust \n#[derive(Intuple)]\nstruct Struct {a:u32, #[igno] b:u32, c:u32}\nfn main(){\n    let strct = Struct::from((2,1));     \n    // =\u003e {a:2, b:0, c:1}  \n    let tuple: (u32, u32) = strct.into();\n    // =\u003e (2, 1)\n}\n```\n## Recursion\n🦊 convert recursively with `#[recursive]`/`#[rcsv]`\u003cbr\u003e\n🦐 or `#[intuple(rcsv)]`/`#[intuple(recursive)]`\u003cbr\u003e\n🐼 recursive fields need to derive `Intuple`\n```rust \n#[derive(Intuple)]\nstruct Struct {a:u32, b:u32, c:u32}\n#[derive(Intuple)]\nstruct Recursive {a:u32, #[recursive] b:Struct, c:u32}\nfn main(){\n    let rcsv: Recursive = (9,(3,2,1),8).into(); \n    // =\u003e Recursive{a:9, b:Struct{a:3,b:2,c:1}, c:8}\n    let tuple = rcsv.into_tuple(); \n    // =\u003e (9,(3,2,1),8)\n}\n```\n🦆 recursion also works with `.as_tuple_ref()` and `as_tuple_ref_mut()`\n```rust \n#[derive(Intuple)]\nstruct Struct {a:u32, b:u32, c:u32}\n#[derive(Intuple)]\nstruct Recursive {a:u32, #[recursive] b:Struct, c:u32}\nfn main(){\n    let rcsv = Recursive::from((9,(3,2,1),8)); \n    let tuple = rcsv.as_tuple_ref(); \n    // =\u003e (\u00269,(\u00263,\u00262,\u00261),\u00268)\n}\n```\n## Enums\n🙉 converting enums to tuples isn't as straight forward as structs, therefore two methods are implemented!\n### 🐍 1. Positional\n🐆 using `Intuple` - no additional enums or structs are generated\u003cbr\u003e\n🐢 field tuples are wrapped in an `Option\u003c\u003e`, which are inside another tuple\u003cbr\u003e\n🦎 the outer tuple has as many fields as there are enum variants\u003cbr\u003e\n🐊 the required `None` variant will convert to `(None,None,None,...)`\u003cbr\u003e\n🐉 any other variant will occupy a slot, depending on its position `(None,Some(tuple),None,...)`\n```rust \n// Positional\n#[derive( Intuple, Debug )]\n// enums require a 'None' variant\nenum Enum { None, Unit, Unnamed(u32,u32), Another(u8,u8) }\nfn main(){\n    let enum = Enum::Unnamed(1,2); \n    let tuple = enum.as_tuple_ref(); \n    // =\u003e (None, Some((\u00261,\u00262)), None)\n    let tuple = enum.into_tuple(); \n    // =\u003e (None, Some((1,2)), None)\n    let enum = Enum::None; \n    let tuple = rcsv.into_tuple(); \n    // =\u003e (None,None,None)\n}\n```\n### 🦊 2. Generated Tuple Enums\n🐈 using `IntupleEnum` -  **three** additional enums will be generated: \u003cbr\u003e\n🐕 `{EnumName}Intuple`, `{EnumName}IntupleRef` and `{EnumName}IntupleRefMut`\u003cbr\u003e\n🦄 each of those will use the original variant names and contain a tuple\u003cbr\u003e\n🐔 to set derives for them, use `#[intuple(derive(...))]`\u003cbr\u003e\n⚠ to use them recursivly **ANYWHERE**, use `#[recursive_enum]` or `#[rcsve]`\u003cbr\u003e\n🦢 `.into()`/`.from(..)` are implemented, but the custom methods change to:\u003cbr\u003e\n🐓 `.from_tuple_enum(..)`, `.into_tuple_enum()`, `.as_tuple_enum_ref()` and `.as_tuple_enum_ref_mut()`\n```rust \n// Generated\n#[derive( IntupleEnum, Debug )]\n#[intuple(derive( Debug ))]\nenum Enum { Unit, Unnamed(u32,u32), Another(u8,u8) }\nfn main(){\n    let enum = Enum::Unnamed(1,2); \n    let tuple = enum.as_tuple_enum_ref(); \n    // =\u003e EnumIntupleRef::Unnamed((\u00261,\u00262))\n    let tuple = enum.into_tuple_enum(); \n    // =\u003e EnumIntupleRef::Unnamed((1,2))\n}\n```\n## Example: Serde - Thinking out of the box\n🦄 You could use `serde` without implementing Serialize/Deserialize\u003cbr\u003e\n🐔 This only works with the **positional** enum tuples!\n```rust\nuse intuple::*;\n\n#[derive(Intuple)]\nstruct Named{a:u32, b:u32, c:u32, d:u32, e:u32, f:u32}\n\nfn main(){\n    let named = Named::from((1,2,3,4,5,6));\n    let json = serde_json::to_string(\u0026named.as_tuple_ref()).unwrap();\n    println!(\"{}\",json); //=\u003e \"[1,2,3,4,5,6]\"\n\n    let tuple = serde_json::from_str::\u003c\u003cNamed as Intuple\u003e::Tuple\u003e(\u0026json).unwrap();\n    let named_again = Named::from(tuple);\n    // named == named_again\n}\n```\n## More Information\n\u003ca href=\"CHANGELOG.md\"\u003e🦎 Changelog\u003c/a\u003e\u003cbr\u003e\n[🐱 GitHub](https://github.com/dekirisu/intuple)\u003cbr\u003e\n[👾 Discord Server](https://discord.gg/kevWvBuPFg)\u003cbr\u003e\n\n---\n### License\n\u003csup\u003e\nLicensed under either of \u003ca href=\"LICENSE-APACHE\"\u003eApache License, Version\n2.0\u003c/a\u003e or \u003ca href=\"LICENSE-MIT\"\u003eMIT license\u003c/a\u003e at your option.\n\u003c/sup\u003e\n\u003cbr\u003e\n\u003csub\u003e\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in this crate by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n\u003c/sub\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdekirisu%2Fintuple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdekirisu%2Fintuple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdekirisu%2Fintuple/lists"}