{"id":20145872,"url":"https://github.com/usagi/tia","last_synced_at":"2025-04-09T19:20:44.669Z","repository":{"id":54853538,"uuid":"287892042","full_name":"usagi/tia","owner":"usagi","description":"tia; trait, impl accessors | automatic for Rust, proc-macro","archived":false,"fork":false,"pushed_at":"2022-05-05T11:32:28.000Z","size":70,"stargazers_count":5,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T21:11:23.550Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/usagi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-16T07:03:07.000Z","updated_at":"2023-07-25T14:38:21.000Z","dependencies_parsed_at":"2022-08-14T04:50:25.616Z","dependency_job_id":null,"html_url":"https://github.com/usagi/tia","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usagi%2Ftia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usagi%2Ftia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usagi%2Ftia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usagi%2Ftia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/usagi","download_url":"https://codeload.github.com/usagi/tia/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248095007,"owners_count":21046773,"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":[],"created_at":"2024-11-13T22:18:32.873Z","updated_at":"2025-04-09T19:20:44.642Z","avatar_url":"https://github.com/usagi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![github]](https://github.com/usagi/tia)\u0026ensp;[![crates-io]](https://crates.io/crates/tia)\u0026ensp;[![docs-rs]](https://docs.rs/tia)\u003cbr\u003e\n\n[github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge\u0026labelColor=555555\u0026logo=github\n[crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge\u0026labelColor=555555\u0026logo=rust\n[docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge\u0026labelColor=555555\u0026logoColor=white\u0026logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K\n\n# tia; trait, impl accessors | automatic\n\nThis is a syntax sugar proc-macro crate for `trait`, `impl` accessors patterns. `tia` generate to an accessor `impl`s of an indivisual `trait`s for any `struct`|`enun`|`union`s.\n\n## Features\n\n- `tia` can be generate a `impl` codes automatically.\n- Target types: `struct` | `enum` | `union`.\n- Setting levels: {for all fields} | {per field}.\n- `trait` supporting: Can be generate with multiple `trait`s. (See also the Example-3 in below.)\n- Generative accessors: Getter-like {move, `Copy`, `\u0026`, `\u0026mut`}, Setter-like { move, `Copy`, `Clone`, `Into` }. (See also the Example-1,2 and Reference/tia directive section.)\n- Useful +features: { `print`, `file-pretty`, `include`, `disable` }. (See also the Reference/features section.)\n- Naming patters: { prefix, suffix, fullname }. (See also the Reference/tia directive section.)\n\n## Example\n\n### Example-1; The introduction of `tia`\n\nIt is minimal, very simple version. Without `trait`s complex.\n\n```rust\nuse tia::Tia;  // 1. use\n\n#[derive(Tia)] // 2. derive\n#[tia(rg)]     // 3. tia directives\nstruct MyStruct\n{\n foo: i32,\n bar: String\n}\n\nfn main()\n{\n let mys = MyStruct{ foo: 123, bar: \"Hello\".into() };\n let foo = mys.get_foo(); // \u003c-- 4. !! generated by tia automatically !!\n let bar = mys.get_bar(); // \u003c-- 5. !! generated by tia automatically !!\n println!(\"foo={} bar={}\", foo, bar );\n}\n```\n\n`cargo run`, then you will get the output:\n\n```sh\nfoo=123 bar=Hello\n```\n\n- (1,2) are preparing.\n- (3) is tia directive for the struct-level.\n- (4,5) are an automatic generated accessors by `tia`.\n\nThe automatic generated code is:\n\n```rust\nimpl MyStruct\n{\n pub fn get_foo(\u0026self) -\u003e \u0026i32\n {\n  \u0026self.foo\n }\n\n pub fn get_bar(\u0026self) -\u003e \u0026String\n {\n  \u0026self.bar\n }\n}\n```\n\nIt could be output to `src/.tia/MyStruct` if use `file-pretty` features in `Cargo.toml`:\n\n```toml\n[dependencies]\ntia={ version=\"*\", features=[\"file-pretty\"] }\n```\n\n\n### Example-2; A little complex/practical usage\n\n```rust\nuse tia::Tia; // use\n\n#[derive(Tia, Debug, Default)] // derive\n#[tia(rg, s)] // \u003c-- tia directives, for all fields\nstruct MyStruct\n{\n #[tia(rmg)] // \u003c-- #[tia(rg, s)] + #[tia(rmg)] =\u003e #[tia(rmg, s)]\n foo: i32,\n #[tia(rsi)] // \u003c-- #[tia(rg, s)] + #[tia(rsi)] =\u003e #[tia(rg, rsi)]\n bar: String,\n\n baz: f64, // \u003c-- #[tia(rg, s)]\n\n #[tia(g)] // \u003c-- #[tia(rg, s)] + #[tia(g)] =\u003e #[tia(g, s)] !! NOTE: Could be use for Copy-ables such as u8, but g pattern could not be use non-Copy-ables such as Vec\u003cu8\u003e\n brabrabra: u8,\n\n #[tia(gm)] // \u003c-- #[tia(rg, s)] + #[tia(g)] =\u003e #[tia(gm, s)] !! WARNING: Could be move any types, but gm pattern will drop self\n hogefuga: Vec\u003cu8\u003e\n}\n\nfn main()\n{\n let mut mys = MyStruct::default();\n\n // rmg; reference-mut-getter\n // with per-field level directive overwriting.\n {\n  let foo = mys.get_foo(); // \u003c-- \u0026mut i32\n  *foo = 42;\n  dbg!(\u0026foo);\n  dbg!(\u0026mys);\n }\n\n // rsi: reference-setter-into\n // with per-field level directive overwriting.\n {\n  let a: \u0026str = \"Hello, \";\n  let b: String = String::from(\"tia.\");\n  let c: \u0026String = \u0026b;\n\n  mys.set_bar(a); // \u0026str\n  println!(\"a: mys.bar = {}\", mys.get_bar());\n\n  mys.set_bar(b.clone()); // String; This effect move, thus the example is a -\u003e c -\u003e b\n  println!(\"b: mys.bar = {}\", mys.get_bar());\n\n  mys.set_bar(c); // \u0026String\n  println!(\"c: mys.bar = {}\", mys.get_bar());\n }\n\n let x = mys.get_brabrabra(); // it will be Copy, mys will live\n dbg!(x, \u0026mys);\n\n let y = mys.get_hogefuga(); // gm, get-move accessor will be drop mys\n dbg!(y);\n // mys was dropped, it could not be compile.\n //dbg!(mys)\n}\n```\n\n`cargo run`:\n\n```rust\n[src\\main.rs:30] \u0026foo = 42\n[src\\main.rs:31] \u0026mys = MyStruct {\n    foo: 42,\n    bar: \"\",\n    baz: 0.0,\n    brabrabra: 0,\n    hogefuga: [],\n}\na: mys.bar = Hello,\nb: mys.bar = tia.\nc: mys.bar = tia.\n[src\\main.rs:52] x = 0\n[src\\main.rs:52] \u0026mys = MyStruct {\n    foo: 42,\n    bar: \"tia.\",\n    baz: 0.0,\n    brabrabra: 0,\n    hogefuga: [],\n}\n[src\\main.rs:55] y = []\n```\n\n### Example-3; `trait` usage\n\n```rust\nuse tia::Tia;\n\ntrait FooGettable\u003cT\u003e{ fn get_foo(\u0026self) -\u003e T; }\ntrait Fruit{ fn get_bar(\u0026self) -\u003e \u0026String; }\ntrait Sushi{ fn tuna(\u0026self) -\u003e u8; fn avocado(\u0026mut self, v: u8); }\n\n//include!(\".tia/MyStruct.rs\");\n#[derive(Tia, Debug, Default)] // derive\nstruct MyStruct\n{\n #[tia(s, \"FooGettable\u003ci32\u003e\", g)]\n foo: i32,\n #[tia(\"Fruit\",rg,\"\",rsi)]\n bar: String,\n #[tia(\"Sushi\",g*=\"tuna\",s*=\"avocado\")] // \u003c- `g` and `s`: Sushi trait\n baz: u8\n}\n\nfn main()\n{\n let mut mys = MyStruct::default();\n mys.set_foo(123);\n mys.set_bar(\"meow\");\n let foo_gettable = \u0026mys as \u0026dyn FooGettable\u003ci32\u003e;\n let fruit = \u0026mys as \u0026dyn Fruit;\n println!(\"{}, {}\", foo_gettable.get_foo(), fruit.get_bar() );\n let sushi = \u0026mut mys as \u0026mut dyn Sushi;\n sushi.avocado(32);\n println!(\"{}\", sushi.tuna());\n}\n```\n\nThen `cargo run`:\n\n```sh\n123, meow\n32\n```\n\nThe generated code with `print`, `file` or `file-pretty` features:\n\n```rust\nimpl FooGettable\u003ci32\u003e for MyStruct\n{\n fn get_foo(\u0026self) -\u003e i32\n {\n  self.foo\n }\n}\nimpl MyStruct\n{\n pub fn set_bar\u003cT: Into\u003cString\u003e\u003e(\u0026mut self, v: T)\n {\n  self.bar = v.into();\n }\n\n pub fn set_foo(\u0026mut self, v: i32)\n {\n  self.foo = v;\n }\n}\nimpl Fruit for MyStruct\n{\n fn get_bar(\u0026self) -\u003e \u0026String\n {\n  \u0026self.bar\n }\n}\nimpl Sushi for MyStruct\n{\n fn avocado(\u0026mut self, v: u8)\n {\n  self.baz = v;\n }\n\n fn tuna(\u0026self) -\u003e u8\n {\n  self.baz\n }\n}\n```\n\n## Reference\n\n### Usage\n\n1. Preparing, add `tia=\"*\"` in `[dependencies]` section of the project `Cargo.toml` file. ( Or I like `cargo add tia` via [cargo-edit][] )\n   - FYI: The `file-pretty` features is good tool for your debugging. Read the bottom section \"features\" if you want.\n2. Use:\n   1. Write `#[derive(Tia)]` proc-macro on head of your struct|enum|union.\n   2. Write `#[tia(...)]` proc-macro below the `#[derive(Tia)]` (for struct|enum|union-level settings) or top of the specific fields.\n      - `...` is explanate in the next section \"tia directives\".\n\n[cargo-edit]: https://github.com/killercup/cargo-edit\n\n### tia directives\n\n`tia`'s proc-macro can parse the pattern:\n\n```\n#[tia( $tia_directive_0, $tia_directive_1,$tia_directive_2, ... )]\n```\n\nAnd the `$tia_directive` pattern:\n\n1. Accessor directive\n   - Accessors:\n     - Getter accessor like:\n       - `gm` =\u003e (`[g]et [m]ove`) **⚠ Move ⚠** pattern, it is NOT use for casually; like `fn (self) -\u003e i32 { self.value }`\n       - `g` =\u003e (`[g]et`) For `Copy`-able values, for use a primitive types such as `u8`, `f32` or a `impl Copy`-ed types; like `return \u0026self.value`.\n       - `rg` =\u003e (`[r]eference [g]et`) Return a reference `\u0026` pattern. It can be use in casually for most situations.\n       - `rmg` =\u003e (`[r]eference [m]ut [g]et`) Return a reference mutable `\u0026mut`. Sometimes useful, and sometimes so complex and difficult.\n     - Setter accelike:\n       - `s` =\u003e (`[s]et`) Raw value move pattern.\n       - `rs` =\u003e (`[r]eference [s]et`) Reference `\u0026` pattern, for `Copy`-able types.\n       - `rsc` =\u003e (`[r]eference [s]et [c]lone`) `Clone` pattern, for `Clone`-able types such as `String`. This pattern require the same type for the input.\n       - `rsi` =\u003e (`[r]eference [s]et [i]nto`) `Into` pattern, for `Into`-able types such as `String`. This pattern could be type conversions. For eg, `\u0026str`|`String`|`\u0026String` and more types are input to `String` with this pattern.\n   - Naming policy\n     - Default ( eg. `g`, `rg` `rgi`) =\u003e Getters are same as the Prefix with \"get\", Setters are same as the Prefix with \"set\".\n     - `g=\"my_awesome_prefix\"` =\u003e Prefix with specialized prefix-part string pattern. It will be generate `fn my_awesome_prefix_xxxx` for `xxxx` field symbol.\n     - `g+=\"my_awesome_suffix\"` =\u003e Suffix with specialized suffix-part string pattern. It will be generate `fn xxxx_my_awesome_suffix` for `xxxx` field symbol.\n     - `g*=\"my_awesome_fullname\"` =\u003e Fullname pattern. It will be generate `fn my_awesome_fullname` for a field.\n2. Trait directive\n   - Default ( no trait directives ) =\u003e It will be generate `impl for MyStruct` codes for a fields.\n   - `\"TraitSymbol\"` =\u003e It will be generate `impl TraitSymbol for MyStruct` codes for a fields that appear in the after of this directive.\n   - `\"\"` =\u003e It will be generate `impl for MyStruct` codes for a fields that appear in the after of this directive.\n\n### features\n\n#### `disable`\n\nUsage example:\n\n```toml\n[dependencies]\ntia={ version=\"*\", features=[\"disable\"] }\n```\n\n- `tia` will be output nothing.\n- But `tia` is not removed, thus it allow the `#[derive(Tia)]` and `#[tia(...)]` proc-macros with no effects.\n\n#### `print`\n\nUsage example:\n\n```toml\n[dependencies]\ntia={ version=\"*\", features=[\"print\"] }\n```\n\n- `tia` will be output the generated code to STDERR.\n    -  But it is difficully to human eyes, thus `file-pretty` is better for human eyes.\n\n#### `file`|`file-pretty`\n\nUsage example:\n\n```toml\n[dependencies]\ntia={ version=\"*\", features=[\"file-pretty\"] }\n```\n\n- `tia` will be output/update the generated code to the file such as `src/.tia/MyStruct.rs`.\n- This file is not for use in build, but if you want check the generated code with your eyes then it helpful.\n\nWhat's the difference of `file` and `file-pretty`:\n\n- `file` will be output the raw generated code. It is very compressed.\n- `file-pretty` will be output the raw generated code, and then apply `rustfmt` automatically.\n  - note: this feature reqwire the `rustfmt` command in your development environment. (It is not a lib crate dependency.)\n\n#### `include`|`include-pretty`|`include-force`\n\nUsage example:\n\n```toml\n[dependencies]\ntia={ version=\"*\", features=[\"include-pretty\"] }\n```\n\n`tia` will be:\n\n1. Generate codes if not exists.\n2. Generate `include!(...)` macro such as `include!(\"src/.tia/MyStruct\")` instead.\n\nWhat's the difference of `include`, `include-pretty` and `include-force`:\n\n- `include` will be generate (=`file`) code if the generated code is not found.\n- `include-pretty` will be generate and prettify (=`file-pretty`) if the generated code is not found.\n- `include-force` will not be generate if the generated code is not found, maybe build will stop with an error(s).\n\n## Note\n\n`tia` provide a useful syntax sugar, it will helpful if you should impl many interface-like specifications. For eg, something designed for object-oriented paradigm mainly languages such as C#, Java, C++, or complex data definition based by UML such as XMLSchema. But, it is just a syntax sugar. Please do not overdose `tia` unnecessarily.\n\n## LICENSE\n\n- [MIT](LICENSE.md)\n\n## Contributor\n\n- [@yrashk](https://github.com/yrashk)\n\nThank you!😍\n\n## Author\n\n- USAGI.NETWORK / Usagi Ito \u003chttps://github.com/usagi/\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusagi%2Ftia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusagi%2Ftia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusagi%2Ftia/lists"}