{"id":13599819,"url":"https://github.com/magiclen/educe","last_synced_at":"2025-04-12T14:19:06.846Z","repository":{"id":52471323,"uuid":"198966166","full_name":"magiclen/educe","owner":"magiclen","description":"This crate offers procedural macros designed to facilitate the swift implementation of Rust's built-in traits.","archived":false,"fork":false,"pushed_at":"2024-08-01T14:42:20.000Z","size":549,"stargazers_count":141,"open_issues_count":14,"forks_count":15,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T14:19:02.812Z","etag":null,"topics":["rust"],"latest_commit_sha":null,"homepage":"","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/magiclen.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-26T07:11:00.000Z","updated_at":"2025-03-10T06:33:39.000Z","dependencies_parsed_at":"2024-01-05T13:34:51.437Z","dependency_job_id":"0d37f972-bd18-44cf-8b69-3dbf2e85e930","html_url":"https://github.com/magiclen/educe","commit_stats":{"total_commits":118,"total_committers":6,"mean_commits":"19.666666666666668","dds":"0.11016949152542377","last_synced_commit":"bb0d520f8dd1f998d56c150a15dd044fc3cb3db1"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Feduce","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Feduce/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Feduce/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclen%2Feduce/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magiclen","download_url":"https://codeload.github.com/magiclen/educe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248578876,"owners_count":21127714,"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":["rust"],"created_at":"2024-08-01T17:01:12.482Z","updated_at":"2025-04-12T14:19:06.809Z","avatar_url":"https://github.com/magiclen.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"Educe\n====================\n\n[![CI](https://github.com/magiclen/educe/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/educe/actions/workflows/ci.yml)\n\nThis crate offers procedural macros designed to facilitate the swift implementation of Rust's built-in traits.\n\n## Features\n\nBy default, every trait this crate supports will be enabled. You can disable all of them by turning off the default features and enable only the traits that you want to use by adding them to the `features` explicitly.\n\nFor example,\n\n```toml\n[dependencies.educe]\nversion = \"*\"\nfeatures = [\"Debug\", \"Clone\", \"Copy\", \"Hash\", \"Default\"]\ndefault-features = false\n```\n\n## Traits\n\n#### Debug\n\nUse `#[derive(Educe)]` and `#[educe(Debug)]` to implement the `Debug` trait for a struct, enum, or union. This allows you to modify the names of your types, variants, and fields. You can also choose to ignore specific fields or set a method to replace the `Debug` trait. Additionally, you have the option to format a struct as a tuple and vice versa.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Debug)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Change the Name of a Type, a Variant or a Field\n\nThe `name` parameter can rename a type, a variant or a field. If you set it to `false`, the name can be ignored or forced to show otherwise.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug(name(Struct2)))]\nstruct Struct {\n    #[educe(Debug(name(f)))]\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Debug(name = true))]\nenum Enum {\n    #[educe(Debug(name = false))]\n    V1,\n    #[educe(Debug(name(V)))]\n    V2 {\n        #[educe(Debug(name(f)))]\n        f1: u8,\n    },\n    #[educe(Debug(name = false))]\n    V3(u8),\n}\n```\n\n###### Ignore Fields\n\nThe `ignore` parameter can ignore a specific field.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug)]\nstruct Struct {\n    #[educe(Debug(ignore))]\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Debug)]\nenum Enum {\n    V1,\n    V2 {\n        #[educe(Debug(ignore))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Debug(ignore))]\n        u8\n    ),\n}\n```\n\n###### Fake Structs and Tuples\n\nWith the `named_field` parameter, structs can be formatted as tuples and tuples can be formatted as structs.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug(named_field = false))]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Debug)]\nenum Enum {\n    V1,\n    #[educe(Debug(named_field = false))]\n    V2 {\n        f1: u8,\n    },\n    #[educe(Debug(named_field = true))]\n    V3(\n        u8,\n        #[educe(Debug(name(value)))]\n        i32\n    ),\n}\n```\n\n###### Use Another Method to Handle the Formatting\n\nThe `method` parameter can be utilized to replace the implementation of the `Debug` trait for a field, eliminating the need to implement the `Debug` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nuse std::fmt::{self, Formatter};\n\nfn fmt\u003cT\u003e(_s: \u0026T, f: \u0026mut Formatter\u003c'_\u003e) -\u003e fmt::Result {\n    f.write_str(\"Hi\")\n}\n\n#[derive(Educe)]\n#[educe(Debug)]\nenum Enum\u003cT\u003e {\n    V1,\n    V2 {\n        #[educe(Debug(method(fmt)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Debug(method(std::fmt::UpperHex::fmt)))]\n        u8,\n        #[educe(Debug(method(fmt)))]\n        T\n    ),\n}\n```\n\n###### Generic Parameters Bound to the `Debug` Trait or Others\n\nGeneric parameters will be automatically bound to the `Debug` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\nuse std::fmt::{self, Formatter};\n\nfn fmt\u003cD\u003e(_s: \u0026D, f: \u0026mut Formatter\u003c'_\u003e) -\u003e fmt::Result {\n    f.write_str(\"Hi\")\n}\n\n#[derive(Educe)]\n#[educe(Debug(bound(T: std::fmt::Debug)))]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(Debug(method(fmt)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nIn the above case, `T` is bound to the `Debug` trait, but `K` is not.\n\nOr, you can have `educe` replicate the behaviour of `std`'s `derive`'s, where a bound is produced for *every* generic parameter, without regard to how it's used in the structure:\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug(bound(*)))]\nstruct Struct\u003cT\u003e {\n    #[educe(Debug(ignore))]\n    f: T,\n}\n```\n\nThis can be useful if you don't want to make the trait implementation part of your permanent public API. In this example, `Struct\u003cT\u003e` doesn't implement `Debug` unless `T` does. I.e., it has a `T: Debug` bound even though that's not needed right now. Later we might want to display `f`; we wouldn't then need to make a breaking API change by adding the bound.\n\nThis was the behaviour of `Trait(bound)` in educe 0.4.x and earlier.\n\n###### Union\n\nA union will be formatted as a `u8` slice because we don't know its fields at runtime. The fields of a union cannot be ignored, renamed, or formatted with other methods. The implementation is **unsafe** because it may expose uninitialized memory.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Debug(unsafe))]\nunion Union {\n    f1: u8,\n    f2: i32,\n}\n```\n\n#### Clone\n\nUse `#[derive(Educe)]` and `#[educe(Clone)]` to implement the `Clone` trait for a struct, an enum, or a union. You can set a method to replace the `Clone` trait.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Clone)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Clone)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Use Another Method to Perform Cloning\n\nThe `method` parameter can be utilized to replace the implementation of the `Clone` trait for a field, eliminating the need to implement the `Clone` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nfn clone(v: \u0026u8) -\u003e u8 {\n    v + 100\n}\n\ntrait A {\n    fn add(\u0026self, rhs: u8) -\u003e Self;\n}\n\nfn clone2\u003cT: A\u003e(v: \u0026T) -\u003e T {\n    v.add(100)\n}\n\n#[derive(Educe)]\n#[educe(Clone)]\nenum Enum\u003cT: A\u003e {\n    V1,\n    V2 {\n        #[educe(Clone(method(clone)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Clone(method(clone2)))]\n        T\n    ),\n}\n```\n\n###### Generic Parameters Bound to the `Clone` Trait or Others\n\nGeneric parameters will be automatically bound to the `Clone` trait if necessary. If the `#[educe(Copy)]` attribute exists, they will be bound to the `Copy` trait.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Clone)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\ntrait A {\n    fn add(\u0026self, rhs: u8) -\u003e Self;\n}\n\nfn clone\u003cT: A\u003e(v: \u0026T) -\u003e T {\n    v.add(100)\n}\n\n#[derive(Educe)]\n#[educe(Clone(bound(T: std::clone::Clone)))]\nenum Enum\u003cT, K: A\u003e {\n    V1,\n    V2 {\n        #[educe(Clone(method(clone)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nIn the above case, `T` is bound to the `Clone` trait, but `K` is not.\n\nOr, you can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.\n\n```rust\nuse educe::Educe;\n\ntrait A {\n    fn add(\u0026self, rhs: u8) -\u003e Self;\n}\n\nfn clone\u003cT: A\u003e(v: \u0026T) -\u003e T {\n    v.add(100)\n}\n\n#[derive(Educe)]\n#[educe(Clone(bound(*)))]\nstruct Struct\u003cT: A\u003e {\n    #[educe(Clone(method(clone)))]\n    f: T,\n}\n```\n\n###### Union\n\nRefer to the introduction of the `#[educe(Copy)]` attribute.\n\n#### Copy\n\nUse `#[derive(Educe)]` and `#[educe(Copy)]` to implement the `Copy` trait for a struct, an enum, or a union.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Copy, Clone)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Copy, Clone)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Generic Parameters Bound to the `Copy` Trait or Others\n\nAll generic parameters will be automatically bound to the `Copy` trait.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Copy, Clone)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\ntrait A {\n    fn add(\u0026self, rhs: u8) -\u003e Self;\n}\n\nfn clone\u003cT: A\u003e(v: \u0026T) -\u003e T {\n    v.add(100)\n}\n\n#[derive(Educe)]\n#[educe(Copy, Clone(bound(T: Copy, K: A + Copy)))]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(Clone(method(clone)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nNote that utilizing custom cloning methods for a type that implements the `Copy` and `Clone` traits may not be entirely appropriate.\n\n###### Union\n\nThe `#[educe(Copy, Clone)]` attribute can be used for a union. The fields of a union cannot be cloned with other methods.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Copy, Clone)]\nunion Union {\n    f1: u8,\n}\n```\n\n#### PartialEq\n\nUse `#[derive(Educe)]` and `#[educe(PartialEq)]` to implement the `PartialEq` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `PartialEq` trait.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(PartialEq)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Ignore Fields\n\nThe `ignore` parameter can ignore a specific field.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq)]\nstruct Struct {\n    #[educe(PartialEq(ignore))]\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(PartialEq)]\nenum Enum {\n    V1,\n    V2 {\n        #[educe(PartialEq(ignore))]\n        f1: u8,\n    },\n    V3(\n        #[educe(PartialEq(ignore))]\n        u8\n    ),\n}\n```\n\n###### Use Another Method to Perform Comparison\n\nThe `method` parameter can be utilized to replace the implementation of the `PartialEq` trait for a field, eliminating the need to implement the `PartialEq` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nfn eq(a: \u0026u8, b: \u0026u8) -\u003e bool {\n    a + 1 == *b\n}\n\ntrait A {\n    fn is_same(\u0026self, other: \u0026Self) -\u003e bool;\n}\n\nfn eq2\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e bool {\n    a.is_same(b)\n}\n\n#[derive(Educe)]\n#[educe(PartialEq)]\nenum Enum\u003cT: A\u003e {\n    V1,\n    V2 {\n        #[educe(PartialEq(method(eq)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(PartialEq(method(eq2)))]\n        T\n    ),\n}\n```\n\n###### Generic Parameters Bound to the `PartialEq` Trait or Others\n\nGeneric parameters will be automatically bound to the `PartialEq` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\ntrait A {\n    fn is_same(\u0026self, other: \u0026Self) -\u003e bool;\n}\n\nfn eq\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e bool {\n    a.is_same(b)\n}\n\n#[derive(Educe)]\n#[educe(PartialEq(bound(T: std::cmp::PartialEq, K: A)))]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(PartialEq(method(eq)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nIn the above case, `T` is bound to the `PartialEq` trait, but `K` is not.\n\nYou can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq(bound(*)))]\nstruct Struct\u003cT\u003e {\n    #[educe(PartialEq(ignore))]\n    f: T,\n}\n```\n\n###### Union\n\nThe `#[educe(PartialEq(unsafe))]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq(unsafe))]\nunion Union {\n    f1: u8,\n    f2: i32\n}\n```\n\n#### Eq\n\nUse `#[derive(Educe)]` and `#[educe(Eq)]` to implement the `Eq` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `PartialEq` trait.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Ignore Fields\n\nThe `ignore` parameter can ignore a specific field.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq)]\nstruct Struct {\n    #[educe(Eq(ignore))]\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq)]\nenum Enum {\n    V1,\n    V2 {\n        #[educe(Eq(ignore))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Eq(ignore))]\n        u8\n    ),\n}\n```\n\n###### Use Another Method to Perform Comparison\n\nThe `method` parameter can be utilized to replace the implementation of the `Eq` trait for a field, eliminating the need to implement the `PartialEq` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nfn eq(a: \u0026u8, b: \u0026u8) -\u003e bool {\n    a + 1 == *b\n}\n\ntrait A {\n    fn is_same(\u0026self, other: \u0026Self) -\u003e bool;\n}\n\nfn eq2\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e bool {\n    a.is_same(b)\n}\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq)]\nenum Enum\u003cT: A\u003e {\n    V1,\n    V2 {\n        #[educe(Eq(method(eq)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Eq(method(eq2)))]\n        T\n    ),\n}\n```\n\n###### Generic Parameters Bound to the `PartialEq` Trait or Others\n\nGeneric parameters will be automatically bound to the `PartialEq` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\ntrait A {\n    fn is_same(\u0026self, other: \u0026Self) -\u003e bool;\n}\n\nfn eq\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e bool {\n    a.is_same(b)\n}\n\n#[derive(Educe)]\n#[educe(PartialEq(bound(T: std::cmp::PartialEq, K: A)), Eq)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(Eq(method(eq)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\n###### Union\n\nThe `#[educe(PartialEq(unsafe), Eq)]` attribute can be used for a union. The fields of a union cannot be compared with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq(unsafe), Eq)]\nunion Union {\n    f1: u8,\n    f2: i32\n}\n```\n\n#### PartialOrd\n\nUse `#[derive(Educe)]` and `#[educe(PartialOrd)]` to implement the `PartialOrd` trait for a struct or enum. You can also choose to ignore specific fields or set a method to replace the `PartialOrd` trait.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Ignore Fields\n\nThe `ignore` parameter can ignore a specific field.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\nstruct Struct {\n    #[educe(PartialOrd(ignore))]\n    f1: u8\n}\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\nenum Enum {\n    V1,\n    V2 {\n        #[educe(PartialOrd(ignore))]\n        f1: u8,\n    },\n    V3(\n        #[educe(PartialOrd(ignore))]\n        u8\n    ),\n}\n```\n\n###### Use Another Method to Perform Comparison\n\nThe `method` parameter can be utilized to replace the implementation of the `PartialOrd` trait for a field, eliminating the need to implement the `PartialOrd` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nuse std::cmp::Ordering;\n\nfn partial_cmp(a: \u0026u8, b: \u0026u8) -\u003e Option\u003cOrdering\u003e {\n    if a \u003e b {\n        Some(Ordering::Less)\n    } else if a \u003c b {\n        Some(Ordering::Greater)\n    } else {\n        Some(Ordering::Equal)\n    }\n}\n\ntrait A {\n    fn value(\u0026self) -\u003e u8;\n}\n\nfn partial_cmp2\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e Option\u003cOrdering\u003e {\n    partial_cmp(\u0026a.value(), \u0026b.value())\n}\n\n#[derive(Educe)]\n#[educe(PartialEq, PartialOrd)]\nenum Enum\u003cT: A\u003e {\n    V1,\n    V2 {\n        #[educe(PartialOrd(method(partial_cmp)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(PartialOrd(method(partial_cmp2)))]\n        T\n    ),\n}\n```\n\n###### Ranking\n\nEach field can add a `#[educe(PartialOrd(rank = priority_value))]` attribute, where `priority_value` is an integer value indicating its comparison precedence (lower values indicate higher priority). The default `priority_value` for a field depends on its ordinal position (lower towards the front) and starts with `isize::MIN`.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\nstruct Struct {\n    #[educe(PartialOrd(rank = 1))]\n    f1: u8,\n    #[educe(PartialOrd(rank = 0))]\n    f2: u8,\n}\n```\n\nFor variants, the discriminant can be explicitly set for comparison.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\n#[repr(u8)]\nenum Enum {\n    Three { f1: u8 } = 3,\n    Two(u8) = 2,\n    One = 1,\n}\n```\n\n###### Generic Parameters Bound to the `PartialOrd` Trait or Others\n\nGeneric parameters will be automatically bound to the `PartialOrd` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\nuse std::cmp::Ordering;\n\ntrait A {\n    fn value(\u0026self) -\u003e u8;\n}\n\nfn partial_cmp\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e Option\u003cOrdering\u003e {\n    a.value().partial_cmp(\u0026b.value())\n}\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd(bound(T: std::cmp::PartialOrd, K: PartialEq + A)))]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(PartialOrd(method(partial_cmp)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nIn the above case, `T` is bound to the `PartialOrd` trait, but `K` is not.\n\nYou can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Educe)]\n#[educe(PartialOrd(bound(*)))]\nstruct Struct\u003cT\u003e {\n    #[educe(PartialOrd(ignore))]\n    f: T,\n}\n```\n\n#### Ord\n\nUse `#[derive(Educe)]` and `#[educe(Ord)]` to implement the `Ord` trait for a struct or enum. You can also choose to ignore specific fields or set a method to replace the `Ord` trait.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Ignore Fields\n\nThe `ignore` parameter can ignore a specific field.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\nstruct Struct {\n    #[educe(Ord(ignore))]\n    f1: u8\n}\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\nenum Enum {\n    V1,\n    V2 {\n        #[educe(Ord(ignore))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Ord(ignore))]\n        u8\n    ),\n}\n```\n\n###### Use Another Method to Perform Comparison\n\nThe `method` parameter can be utilized to replace the implementation of the `Ord` trait for a field, eliminating the need to implement the `Ord` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nuse std::cmp::Ordering;\n\nfn cmp(a: \u0026u8, b: \u0026u8) -\u003e Ordering {\n    if a \u003e b {\n        Ordering::Less\n    } else if a \u003c b {\n        Ordering::Greater\n    } else {\n        Ordering::Equal\n    }\n}\n\ntrait A {\n    fn value(\u0026self) -\u003e u8;\n}\n\nfn cmp2\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e Ordering {\n    cmp(\u0026a.value(), \u0026b.value())\n}\n\n#[derive(Educe)]\n#[educe(PartialEq, Eq, PartialOrd, Ord)]\nenum Enum\u003cT: A\u003e {\n    V1,\n    V2 {\n        #[educe(Ord(method(cmp)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Ord(method(cmp2)))]\n        T\n    ),\n}\n```\n\n###### Ranking\n\nEach field can add a `#[educe(Ord(rank = priority_value))]` attribute, where `priority_value` is an integer value indicating its comparison precedence (lower values indicate higher priority). The default `priority_value` for a field depends on its ordinal position (lower towards the front) and starts with `isize::MIN`.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\nstruct Struct {\n    #[educe(Ord(rank = 1))]\n    f1: u8,\n    #[educe(Ord(rank = 0))]\n    f2: u8,\n}\n```\n\nFor variants, the discriminant can be explicitly set for comparison.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\n#[repr(u8)]\nenum Enum {\n    Three { f1: u8 } = 3,\n    Two(u8) = 2,\n    One = 1,\n}\n```\n\n###### Generic Parameters Bound to the `Ord` Trait or Others\n\nGeneric parameters will be automatically bound to the `Ord` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\nuse std::cmp::Ordering;\n\ntrait A {\n    fn value(\u0026self) -\u003e u8;\n}\n\nfn cmp\u003cT: A\u003e(a: \u0026T, b: \u0026T) -\u003e Ordering {\n    a.value().cmp(\u0026b.value())\n}\n\n#[derive(PartialEq, Eq, Educe)]\n#[educe(PartialOrd, Ord(bound(T: std::cmp::Ord, K: std::cmp::Ord + A)))]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(PartialOrd(method(cmp)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\n#### Hash\n\nUse `#[derive(Educe)]` and `#[educe(Hash)]` to implement the `Hash` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `Hash` trait.\n\n###### Basic Usage\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Hash)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Hash)]\nenum Enum {\n    V1,\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n```\n\n###### Ignore Fields\n\nThe `ignore` parameter can ignore a specific field.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Hash)]\nstruct Struct {\n    #[educe(Hash(ignore))]\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Hash)]\nenum Enum {\n    V1,\n    V2 {\n        #[educe(Hash(ignore))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Hash(ignore))]\n        u8\n    ),\n}\n```\n\n###### Use Another Method for Hashing\n\nThe `method` parameter can be utilized to replace the implementation of the `Hash` trait for a field, eliminating the need to implement the `Hash` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nuse std::hash::{Hash, Hasher};\n\nfn hash\u003cH: Hasher\u003e(_s: \u0026u8, state: \u0026mut H) {\n    Hash::hash(\u0026100, state)\n}\n\nfn hash2\u003cH: Hasher, T\u003e(_s: \u0026T, state: \u0026mut H) {\n    Hash::hash(\u0026100, state)\n}\n\n#[derive(Educe)]\n#[educe(Hash)]\nenum Enum\u003cT\u003e {\n    V1,\n    V2 {\n        #[educe(Hash(method(hash)))]\n        f1: u8,\n    },\n    V3(\n        #[educe(Hash(method(hash2)))]\n        T\n    ),\n}\n```\n\n###### Generic Parameters Bound to the `Hash` Trait or Others\n\nGeneric parameters will be automatically bound to the `Hash` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Hash)]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\nuse std::hash::{Hash, Hasher};\n\ntrait A {\n    fn value(\u0026self) -\u003e u8;\n}\n\nfn hash\u003cH: Hasher, T: A\u003e(s: \u0026T, state: \u0026mut H) {\n    Hash::hash(\u0026s.value(), state)\n}\n\n#[derive(Educe)]\n#[educe(Hash(bound(T: std::hash::Hash, K: A)))]\nenum Enum\u003cT, K\u003e {\n    V1,\n    V2 {\n        #[educe(Hash(method(hash)))]\n        f1: K,\n    },\n    V3(\n        T\n    ),\n}\n```\n\nIn the above case, `T` is bound to the `Hash` trait, but `K` is not.\n\nYou can have `educe` replicate the behaviour of `std`'s `derive`'s by using `bound(*)`. See the [`Debug`](#debug) section for more information.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Hash(bound(*)))]\nstruct Struct\u003cT\u003e {\n    #[educe(Hash(ignore))]\n    f: T,\n}\n```\n\n###### Union\n\nThe `#[educe(PartialEq(unsafe), Eq, Hash(unsafe))]` attribute can be used for a union. The fields of a union cannot be hashed with other methods. The implementation is **unsafe** because it disregards the specific fields it utilizes.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(PartialEq(unsafe), Eq, Hash(unsafe))]\nunion Union {\n    f1: u8,\n    f2: i32\n}\n```\n\n#### Default\n\nUse `#[derive(Educe)]` and `#[educe(Default)]` to implement the `Default` trait for a struct, enum, or union. You can also choose to ignore specific fields or set a method to replace the `Hash` trait.\n\n###### Basic Usage\n\nFor enums and unions, it is necessary to designate a default variant (for enums) and a default field (for unions) unless the enum has only one variant or the union has only one field.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Default)]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Default)]\nenum Enum {\n    V1,\n    #[educe(Default)]\n    V2 {\n        f1: u8,\n    },\n    V3(u8),\n}\n\n#[derive(Educe)]\n#[educe(Default)]\nunion Union {\n    f1: u8,\n    #[educe(Default)]\n    f2: f64,\n}\n```\n\n###### The Default Value for the Entire Type\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Default(expression = Struct { f1: 1 }))]\nstruct Struct {\n    f1: u8\n}\n\n#[derive(Educe)]\n#[educe(Default(expression = Enum::Struct { f1: 1 }))]\nenum Enum {\n    Unit,\n    Struct {\n        f1: u8\n    },\n    Tuple(u8),\n}\n\n#[derive(Educe)]\n#[educe(Default(expression = Union { f1: 1 }))]\nunion Union {\n    f1: u8,\n    f2: f64,\n}\n```\n\nYou may need to activate the `full` feature to enable support for advanced expressions.\n\n###### The Default Values for Specific Fields\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Default)]\nstruct Struct {\n    #[educe(Default = 1)]\n    f1: u8,\n    #[educe(Default = 11111111111111111111111111111)]\n    f2: i128,\n    #[educe(Default = 1.1)]\n    f3: f64,\n    #[educe(Default = true)]\n    f4: bool,\n    #[educe(Default = \"Hi\")]\n    f5: \u0026'static str,\n    #[educe(Default = \"Hello\")]\n    f6: String,\n    #[educe(Default = 'M')]\n    f7: char,\n}\n\n#[derive(Educe)]\n#[educe(Default)]\nenum Enum {\n    Unit,\n    #[educe(Default)]\n    Tuple(\n        #[educe(Default(expression = 0 + 1))]\n        u8,\n        #[educe(Default(expression = -11111111111111111111111111111 * -1))]\n        i128,\n        #[educe(Default(expression = 1.0 + 0.1))]\n        f64,\n        #[educe(Default(expression = !false))]\n        bool,\n        #[educe(Default(expression = \"Hi\"))]\n        \u0026'static str,\n        #[educe(Default(expression = String::from(\"Hello\")))]\n        String,\n        #[educe(Default(expression = 'M'))]\n        char,\n    ),\n}\n\n#[derive(Educe)]\n#[educe(Default)]\nunion Union {\n    f1: u8,\n    f2: i128,\n    f3: f64,\n    f4: bool,\n    #[educe(Default = \"Hi\")]\n    f5: \u0026'static str,\n    f6: char,\n}\n```\n\n###### Generic Parameters Bound to the `Default` Trait or Others\n\nGeneric parameters will be automatically bound to the `Default` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Default)]\nenum Enum\u003cT\u003e {\n    Unit,\n    #[educe(Default)]\n    Struct {\n        f1: T\n    },\n    Tuple(T),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Default(bound(T: std::default::Default)))]\nenum Enum\u003cT\u003e {\n    Unit,\n    #[educe(Default)]\n    Struct {\n        f1: T\n    },\n    Tuple(T),\n}\n```\n\n###### The `new` Associated Function\n\nWith the `#[educe(Default(new))]` attribute, your type will include an additional associated function called `new`. This function can be utilized to invoke the `default` method of the `Default` trait.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Default(new))]\nstruct Struct {\n    f1: u8\n}\n```\n\n#### Deref\n\nUse `#[derive(Educe)]` and `#[educe(Deref)]` to implement the `Deref` trait for a struct or enum.\n\n###### Basic Usage\n\nYou must designate a field as the default for obtaining an immutable reference unless the number of fields is exactly one.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Deref)]\nstruct Struct {\n    f1: u8,\n    #[educe(Deref)]\n    f2: u8,\n}\n\n#[derive(Educe)]\n#[educe(Deref)]\nenum Enum {\n    Struct {\n        f1: u8\n    },\n    Struct2 {\n        f1: u8,\n        #[educe(Deref)]\n        f2: u8,\n    },\n    Tuple(u8),\n    Tuple2(\n        u8,\n        #[educe(Deref)]\n        u8\n    ),\n}\n```\n\n#### DerefMut\n\nUse `#[derive(Educe)]` and `#[educe(DerefMut)]` to implement the `DerefMut` trait for a struct or enum.\n\n###### Basic Usage\n\nYou must designate a field as the default for obtaining an mutable reference unless the number of fields is exactly one.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Deref, DerefMut)]\nstruct Struct {\n    f1: u8,\n    #[educe(Deref, DerefMut)]\n    f2: u8,\n}\n\n#[derive(Educe)]\n#[educe(Deref, DerefMut)]\nenum Enum {\n    Struct {\n        f1: u8\n    },\n    Struct2 {\n        f1: u8,\n        #[educe(Deref, DerefMut)]\n        f2: u8,\n    },\n    Tuple(u8),\n    Tuple2(\n        #[educe(DerefMut)]\n        u8,\n        #[educe(Deref)]\n        u8\n    ),\n}\n```\n\nThe mutable dereferencing fields do not need to be the same as the immutable dereferencing fields, but their types must be consistent.\n\n#### Into\n\nUse `#[derive(Educe)]` and `#[educe(Into(type))]` to implement the `Into\u003ctype\u003e` trait for a struct or enum.\n\n###### Basic Usage\n\nYou need to designate a field as the default for `Into\u003ctype\u003e` conversion unless the number of fields is exactly one. If you don't, educe will automatically try to find a proper one.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Into(u8), Into(u16))]\nstruct Struct {\n    f1: u8,\n    f2: u16,\n}\n\n#[derive(Educe)]\n#[educe(Into(u8))]\nenum Enum {\n    V1 {\n        f1: u8,\n        #[educe(Into(u8))]\n        f2: u8,\n    },\n    V2 (\n        u8\n    ),\n}\n```\n\n###### Use Another Method to Perform Into Conversion\n\nThe `method` parameter can be utilized to replace the implementation of the `Into` trait for a field, eliminating the need to implement the `Into` trait for the type of that field.\n\n```rust\nuse educe::Educe;\n\nfn into(v: u16) -\u003e u8 {\n    v as u8\n}\n\n#[derive(Educe)]\n#[educe(Into(u8))]\nenum Enum {\n    V1 {\n        #[educe(Into(u8, method(into)))]\n        f1: u16,\n    },\n    V2 (\n        u8\n    ),\n}\n```\n\n###### Generic Parameters Bound to the `Into` Trait or Others\n\nGeneric parameters will be automatically bound to the `Into\u003ctype\u003e` trait if necessary.\n\n```rust\nuse educe::Educe;\n\n#[derive(Educe)]\n#[educe(Into(u8))]\nenum Enum\u003cT, K\u003e {\n    V1 {\n        f1: K,\n    },\n    V2 (\n        T\n    ),\n}\n```\n\nOr you can set the where predicates by yourself.\n\n```rust\nuse educe::Educe;\n\nfn into\u003cT\u003e(_v: T) -\u003e u8 {\n    0\n}\n\n#[derive(Educe)]\n#[educe(Into(u8, bound(K: Into\u003cu8\u003e)))]\nenum Enum\u003cT, K\u003e {\n    V1 {\n        f1: K,\n    },\n    V2 (\n        #[educe(Into(u8, method(into)))]\n        T\n    ),\n}\n```\n\n## Crates.io\n\nhttps://crates.io/crates/educe\n\n## Documentation\n\nhttps://docs.rs/educe\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagiclen%2Feduce","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagiclen%2Feduce","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagiclen%2Feduce/lists"}