{"id":15031433,"url":"https://github.com/greyblake/kinded","last_synced_at":"2025-04-05T20:04:16.635Z","repository":{"id":186141218,"uuid":"674730320","full_name":"greyblake/kinded","owner":"greyblake","description":"Generate Rust enum variants without associated data","archived":false,"fork":false,"pushed_at":"2024-03-29T14:29:24.000Z","size":86,"stargazers_count":93,"open_issues_count":4,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T19:01:42.470Z","etag":null,"topics":["enum","macros","rust","rustlang","trait"],"latest_commit_sha":null,"homepage":"https://docs.rs/kinded/latest/kinded/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/greyblake.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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":"2023-08-04T16:15:14.000Z","updated_at":"2025-03-25T12:49:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"96a52902-c2b4-4812-aea5-b5b7b15d7a94","html_url":"https://github.com/greyblake/kinded","commit_stats":{"total_commits":43,"total_committers":4,"mean_commits":10.75,"dds":"0.11627906976744184","last_synced_commit":"76a29979f9deffad183ae9430e8bda217121487a"},"previous_names":["greyblake/kinded"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyblake%2Fkinded","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyblake%2Fkinded/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyblake%2Fkinded/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyblake%2Fkinded/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/greyblake","download_url":"https://codeload.github.com/greyblake/kinded/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393566,"owners_count":20931812,"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","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":["enum","macros","rust","rustlang","trait"],"created_at":"2024-09-24T20:15:39.991Z","updated_at":"2025-04-05T20:04:16.611Z","avatar_url":"https://github.com/greyblake.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e Kinded \u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/greyblake/kinded/actions/workflows/ci.yml\" rel=\"nofollow\"\u003e\u003cimg src=\"https://github.com/greyblake/kinded/actions/workflows/ci.yml/badge.svg\" alt=\"Nutype Build Status\"\u003e\u003c/a\u003e\n\u003ca href=\"https://docs.rs/kinded\" rel=\"nofollow\"\u003e\u003cimg src=\"https://docs.rs/kinded/badge.svg\" alt=\"Nutype Documentation\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/greyblake/kinded/discussions\"\u003e\u003cimg src=\"https://img.shields.io/github/discussions/greyblake/kinded\"/\u003e\u003c/a\u003e\n\u003cp\u003e\n\n\u003cp align=\"center\"\u003eGenerate Rust enum variants without associated data\u003c/p\u003e\n\n\n## Get Started\n\n```rs\nuse kinded::Kinded;\n\n#[derive(Kinded)]\nenum Drink {\n    Mate,\n    Coffee(String),\n    Tea { variety: String, caffeine: bool }\n}\n\nlet drink = Drink::Coffee(\"Espresso\".to_owned());\nassert_eq!(drink.kind(), DrinkKind::Coffee);\n```\n\nNote, the definition of `DrinkKind` enum is generated automatically as well as `Drink::kind()` method.\nTo put it simply you get something similar to the following:\n\n```rs\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\nenum DrinkKind {\n    Mate,\n    Coffee,\n    Tea\n}\n\nimpl Drink {\n    fn kind(\u0026self) -\u003e DrinkKind {\n        Drink::Mate =\u003e DrinkKind::Mate,\n        Drink::Coffee(..) =\u003e DrinkKind::Coffee,\n        Drink::Tea { .. } =\u003e DrinkKind::Tea,\n    }\n}\n```\n\n## Kinded trait\n\nThe library provides `Kinded` trait:\n\n```rs\npub trait Kinded {\n    type Kind: PartialEq + Eq + Debug + Clone + Copy;\n\n    fn kind(\u0026self) -\u003e Self::Kind;\n}\n```\n\nFrom the example above, the derived implementation of `Kinded` for `Drink` resembles the following:\n\n```rs\nimpl Kinded for Drink {\n    type Kind = DrinkKind;\n\n    fn kind(\u0026self) -\u003e DrinkKind { /* implementation */ }\n}\n```\n\nThe `Kinded` trait allows to build abstract functions that can be used with different enum types.\n\n## Get all kind variants\n\nThe kind type gets implementation of `::all()` associated function, which returns a vector with all kind variants:\n\n```rs\nassert_eq!(DrinkKind::all(), [DrinkKind::Mate, DrinkKind::Coffee, DrinkKind::Tea]);\n```\n\n\n## Attributes\n\n### Custom kind type name\n\nBy default the kind type name is generated by adding postfix `Kind` to the original enum name.\nThis can be customized with `kind = ` attribute:\n\n```rs\nuse kinded::Kinded;\n\n#[derive(Kinded)]\n#[kinded(kind = SimpleDrink)]\nenum Drink {\n    Mate,\n    Coffee(String),\n    Tea { variety: String, caffeine: bool }\n}\n```\n\n### Derive traits\n\nBy default the kind type implements the following traits: `Debug`, `Clone`, `Copy`, `PartialEq`, `Eq`, `Display`, `FromStr`, `From\u003cT\u003e`, `From\u003c\u0026T\u003e`.\n\nExtra traits can be derived with `derive(..)` attribute:\n\n```rs\nuse kinded::Kinded;\nuse std::collections::HashSet;\n\n#[derive(Kinded)]\n#[kinded(derive(Hash))]\nenum Drink {\n    Mate,\n    Coffee(String),\n    Tea { variety: String, caffeine: bool }\n}\n\nlet mut drink_kinds = HashSet::new();\ndrink_kinds.insert(DrinkKind::Mate);\n```\n\n### Display trait\n\nImplementation of `Display` trait can be customized in the `serde` fashion:\n\n```rs\nuse kinded::Kinded;\n\n#[derive(Kinded)]\n#[kinded(display = \"snake_case\")]\nenum Drink {\n    VeryHotBlackTea,\n    Milk { fat: f64 },\n}\n\nlet tea = DrinkKind::VeryHotBlackTea;\nassert_eq!(tea.to_string(), \"very_hot_black_tea\");\n```\n\nThe possible values are `\"snake_case\"`, `\"camelCase\"`, `\"PascalCase\"`, `\"SCREAMING_SNAKE_CASE\"`, `\"kebab-case\"`, `\"SCREAMING-KEBAB-CASE\"`, `\"Title Case\"`, `\"lowercase\"`, `\"UPPERCASE\"`.\n\n### FromStr trait\n\nThe kind type implements `FromStr` trait. The implementation tries it's best to parse, checking all the possible cases mentioned above.\n\n```rs\nuse kinded::Kinded;\n\n#[derive(Kinded)]\n#[kinded(display = \"snake_case\")]\nenum Drink {\n    VeryHotBlackTea,\n    Milk { fat: f64 },\n}\n\nassert_eq!(\n    \"VERY_HOT_BLACK_TEA\".parse::\u003cDrinkKind\u003e().unwrap(),\n    DrinkKind::VeryHotBlackTea\n);\n\nassert_eq!(\n    \"veryhotblacktea\".parse::\u003cDrinkKind\u003e().unwrap(),\n    DrinkKind::VeryHotBlackTea\n);\n```\n\n\n## A note about enum-kinds\n\nThere is a very similar crate [enum-kinds](https://github.com/Soft/enum-kinds) that does almost the same job.\n\nHere is what makes `kinded` different:\n* It provides `Kinded` trait, on top of which users can build abstractions.\n* Generates customizable implementation of `Display` trait.\n* Generates implementation of `FromStr` trait.\n* Generates `kind()` function to extra ergonomics.\n\n## A note about the war in Ukraine 🇺🇦\n\nToday I live in Berlin, I have the luxury to live a physically safe life.\nBut I am Ukrainian. The first 25 years of my life I spent in [Kharkiv](https://en.wikipedia.org/wiki/Kharkiv),\nthe second-largest city in Ukraine, 60km away from the border with russia. Today about [a third of my home city is destroyed](https://www.youtube.com/watch?v=ihoufBFSZds) by russians.\nMy parents, my relatives and my friends had to survive the artillery and air attack, living for over a month in basements.\n\nSome of them have managed to evacuate to EU. Some others are trying to live \"normal lifes\" in Kharkiv, doing there daily duties.\nAnd some are at the front line right now, risking their lives every second to protect the rest.\n\nI encourage you to donate to [Charity foundation of Serhiy Prytula](https://prytulafoundation.org/en).\nJust pick the project you like and donate. This is one of the best-known foundations, you can watch a [little documentary](https://www.youtube.com/watch?v=VlmWqoeub1Q) about it.\nYour contribution to the Ukrainian military force is a contribution to my calmness, so I can spend more time developing the project.\n\nThank you.\n\n\n## License\n\nMIT © [Serhii Potapov](https://www.greyblake.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreyblake%2Fkinded","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgreyblake%2Fkinded","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreyblake%2Fkinded/lists"}