{"id":24859614,"url":"https://github.com/valsteen/sort_by_derive","last_synced_at":"2025-10-15T06:30:29.586Z","repository":{"id":59688561,"uuid":"538536583","full_name":"valsteen/sort_by_derive","owner":"valsteen","description":"Derive macro SortBy and helper macros EnumAccessor and EnumSequence, deriving traits `Ord`, `PartialOrd`, `Eq`, `PartialEq` and `Hash` for structs and enums that can't automatically derive from those traits.","archived":false,"fork":false,"pushed_at":"2023-12-21T15:36:12.000Z","size":59,"stargazers_count":2,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-10T08:10:33.008Z","etag":null,"topics":["enum-dispatch","rust","rust-macro"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valsteen.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,"roadmap":null,"authors":null}},"created_at":"2022-09-19T14:15:07.000Z","updated_at":"2023-09-09T14:23:36.000Z","dependencies_parsed_at":"2023-12-21T16:32:18.540Z","dependency_job_id":null,"html_url":"https://github.com/valsteen/sort_by_derive","commit_stats":{"total_commits":39,"total_committers":1,"mean_commits":39.0,"dds":0.0,"last_synced_commit":"31bd69ab1b8ade5c69de9602997e4899c63401f7"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/valsteen/sort_by_derive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valsteen%2Fsort_by_derive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valsteen%2Fsort_by_derive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valsteen%2Fsort_by_derive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valsteen%2Fsort_by_derive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valsteen","download_url":"https://codeload.github.com/valsteen/sort_by_derive/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valsteen%2Fsort_by_derive/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279058339,"owners_count":26094844,"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-10-15T02:00:07.814Z","response_time":56,"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":["enum-dispatch","rust","rust-macro"],"created_at":"2025-01-31T20:40:44.845Z","updated_at":"2025-10-15T06:30:29.322Z","avatar_url":"https://github.com/valsteen.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GitHub](https://img.shields.io/badge/github-valsteen/sort_by_derive-8da0cb?labelColor=555555\u0026logo=github)](https://github.com/valsteen/sort_by_derive)\n[![Crates.io](https://img.shields.io/crates/v/sort_by_derive)](https://crates.io/crates/sort_by_derive)\n[![docs.rs](https://img.shields.io/docsrs/sort_by_derive)](https://docs.rs/sort_by_derive)\n[![Continuous integration](https://github.com/tlaferriere/sort_by_derive/actions/workflows/rust.yml/badge.svg)](https://github.com/valsteen/sort_by_derive/actions/workflows/rust.yml)\n# sort_by_derive\n\n\u003c!-- TOC --\u003e\n* [sort_by_derive](#sortbyderive)\n  * [Usage](#usage)\n    * [SortBy](#sortby)\n    * [EnumAccessor](#enumaccessor)\n      * [Field accessor](#field-accessor)\n    * [EnumSequence](#enumsequence)\n      * [Example](#example)\n\u003c!-- TOC --\u003e\n\nThis crate provides 3 derive macros `SortBy`, `EnumAccessor` and `EnumSequence`.\n\n- `SortBy` derives the traits `Ord`, `PartialOrd`, `Eq`, `PartialEq` and `Hash` on structs that can't automatically derive those traits because they contain unorderable fields such as `f32`.\n- On enums and structs, `SortBy` can also implement a `Ord` trait that calls arbitrary methods - this is particularly useful in combination with enum variant accessor methods derived by `EnumAccessor` an `EnumSequence`\n- `EnumAccessor` derives accessor methods to common fields in variants - so you don't need to write yourself `match` statements to access a field with the same name and type on different variants. This feature is similar to [enum_dispatch](https://crates.io/crates/enum_dispatch), but takes a different approach where structs don't need to implement a trait.\n- `EnumSequence` provides a `enum_sequence` method where the first variant returns `0`, the second `1`, etc. This is useful is you want to implement a custom sorting, while the order of declaration of variant is still relevant as a secondary ordering criteria.\n\n\n## Usage\n\n### SortBy\n\nFields that should be used for sorting are marked with the attribute `#[sort_by]`.\nOther fields will be ignored.\n\n```rust\nuse std::cmp::Ordering;\nuse sort_by_derive::SortBy;\n\n#[derive(SortBy)]\nstruct Something {\n    #[sort_by]\n    a: u16,\n    b: u16\n}\n\nassert_eq!(Something{a: 2, b: 0}.cmp(\u0026Something{a: 1, b: 1}), Ordering::Greater); // a is compared\nassert_eq!(Something{a: 1, b: 0}.cmp(\u0026Something{a: 1, b: 1}), Ordering::Equal); // b is ignored\n```\n\n### EnumAccessor\n\nThis derive macro is similar to [enum_dispatch](https://crates.io/crates/enum_dispatch).\n`enum_dispatch` requires structs to implement a common trait, which can be useful if a common set of functions applies to all variants.\n`EnumAccessor` takes the opposite approach: common fields and methods are declared at enum level, and you can have variants that don't have a given field or method.\nThis may be more practical if there is a large amount of variants and your only concern is accessing fields, because individual structs just hold data.\nThis is typical for events - they represent a state change and are generally consumed as a whole, individual structs have no code of their own.\n\n#### Field accessor\n\nAfter adding `derive(EnumAccessor)` to the enum, fields are declared as `accessor(field: type)` attributes:\n\nThis will derive the accessor methods `fn name(\u0026self) -\u003e \u0026type;` and`fn name_mut(\u0026mut self) -\u003e \u0026mut type;`, and return a reference to the field of the same name on any variant.\n\n```rust\nuse sort_by_derive::EnumAccessor;\n\n#[derive(EnumAccessor)]\n#[accessor(a: u16)]\n#[accessor(b: u16)]\nenum E {\n    Variant1{a: u16, b: u16},\n    Variant2{a: u16, b: u16, c: u32},\n}\n\nlet v1 = E::Variant1{a: 1, b: 1};\nlet mut v2 = E::Variant2{a: 1, b: 1, c: 2};\n\n// Accessor methods are generated for the specified members\nassert_eq!(*v1.a(), 1);\nassert_eq!(*v2.b(), 1);\n\n// Mutable accessors are also generated\n*v2.a_mut() = 2;\nassert_eq!(*v2.a(), 2);\n```\n\nSo you can take any `E`, all variants will have `a`, `a_mut`, `b`, `b_mut`\n\n### EnumSequence\n\nSimply derive `EnumSequence`, and you get `enum_sequence(\u0026self)` which returns a `usize`, starting from `0` and incrementing for each variant.\n\nWhen using enums of enums, creating an accessor to the inner enum's sequence may create a method name ambiguity. To mitigate this, a custom accessor name can be chosen by using `as`, for instance `#[accessor(enum_sequence() as inner_sequence: usize)]`\n\n**Note**: this will create an extension trait `{TypeName}EnumSequence` ( i.e. the type `T` will get a new trait `TEnumSequence` ). This trait will have the same visibility as the type. When using this type from another module, make sure to bring the trait in scope with `use {TypeName}EnumSequence`.\n\n#### Example\n\n```rust\nuse sort_by_derive::EnumSequence;\n\n#[derive(EnumSequence)]\nenum ABC {\n    A(u8),\n    B(String),\n    C { f: String, g: usize }\n}\n\nassert_eq!(ABC::B(\"hi!\".into()).enum_sequence(), 1);\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalsteen%2Fsort_by_derive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalsteen%2Fsort_by_derive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalsteen%2Fsort_by_derive/lists"}