Crates.io | tia |
lib.rs | tia |
version | 1.0.3 |
source | src |
created_at | 2020-08-16 07:03:43.513893 |
updated_at | 2022-05-05 11:32:44.403408 |
description | tia; trait, impl, accessors | automatic |
homepage | |
repository | https://github.com/usagi/tia |
max_upload_size | |
id | 277154 |
size | 53,052 |
This 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.
tia
can be generate a impl
codes automatically.struct
| enum
| union
.trait
supporting: Can be generate with multiple trait
s. (See also the Example-3 in below.)Copy
, &
, &mut
}, Setter-like { move, Copy
, Clone
, Into
}. (See also the Example-1,2 and Reference/tia directive section.)print
, file-pretty
, include
, disable
}. (See also the Reference/features section.)tia
It is minimal, very simple version. Without trait
s complex.
use tia::Tia; // 1. use
#[derive(Tia)] // 2. derive
#[tia(rg)] // 3. tia directives
struct MyStruct
{
foo: i32,
bar: String
}
fn main()
{
let mys = MyStruct{ foo: 123, bar: "Hello".into() };
let foo = mys.get_foo(); // <-- 4. !! generated by tia automatically !!
let bar = mys.get_bar(); // <-- 5. !! generated by tia automatically !!
println!("foo={} bar={}", foo, bar );
}
cargo run
, then you will get the output:
foo=123 bar=Hello
tia
.The automatic generated code is:
impl MyStruct
{
pub fn get_foo(&self) -> &i32
{
&self.foo
}
pub fn get_bar(&self) -> &String
{
&self.bar
}
}
It could be output to src/.tia/MyStruct
if use file-pretty
features in Cargo.toml
:
[dependencies]
tia={ version="*", features=["file-pretty"] }
use tia::Tia; // use
#[derive(Tia, Debug, Default)] // derive
#[tia(rg, s)] // <-- tia directives, for all fields
struct MyStruct
{
#[tia(rmg)] // <-- #[tia(rg, s)] + #[tia(rmg)] => #[tia(rmg, s)]
foo: i32,
#[tia(rsi)] // <-- #[tia(rg, s)] + #[tia(rsi)] => #[tia(rg, rsi)]
bar: String,
baz: f64, // <-- #[tia(rg, s)]
#[tia(g)] // <-- #[tia(rg, s)] + #[tia(g)] => #[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<u8>
brabrabra: u8,
#[tia(gm)] // <-- #[tia(rg, s)] + #[tia(g)] => #[tia(gm, s)] !! WARNING: Could be move any types, but gm pattern will drop self
hogefuga: Vec<u8>
}
fn main()
{
let mut mys = MyStruct::default();
// rmg; reference-mut-getter
// with per-field level directive overwriting.
{
let foo = mys.get_foo(); // <-- &mut i32
*foo = 42;
dbg!(&foo);
dbg!(&mys);
}
// rsi: reference-setter-into
// with per-field level directive overwriting.
{
let a: &str = "Hello, ";
let b: String = String::from("tia.");
let c: &String = &b;
mys.set_bar(a); // &str
println!("a: mys.bar = {}", mys.get_bar());
mys.set_bar(b.clone()); // String; This effect move, thus the example is a -> c -> b
println!("b: mys.bar = {}", mys.get_bar());
mys.set_bar(c); // &String
println!("c: mys.bar = {}", mys.get_bar());
}
let x = mys.get_brabrabra(); // it will be Copy, mys will live
dbg!(x, &mys);
let y = mys.get_hogefuga(); // gm, get-move accessor will be drop mys
dbg!(y);
// mys was dropped, it could not be compile.
//dbg!(mys)
}
cargo run
:
[src\main.rs:30] &foo = 42
[src\main.rs:31] &mys = MyStruct {
foo: 42,
bar: "",
baz: 0.0,
brabrabra: 0,
hogefuga: [],
}
a: mys.bar = Hello,
b: mys.bar = tia.
c: mys.bar = tia.
[src\main.rs:52] x = 0
[src\main.rs:52] &mys = MyStruct {
foo: 42,
bar: "tia.",
baz: 0.0,
brabrabra: 0,
hogefuga: [],
}
[src\main.rs:55] y = []
trait
usageuse tia::Tia;
trait FooGettable<T>{ fn get_foo(&self) -> T; }
trait Fruit{ fn get_bar(&self) -> &String; }
trait Sushi{ fn tuna(&self) -> u8; fn avocado(&mut self, v: u8); }
//include!(".tia/MyStruct.rs");
#[derive(Tia, Debug, Default)] // derive
struct MyStruct
{
#[tia(s, "FooGettable<i32>", g)]
foo: i32,
#[tia("Fruit",rg,"",rsi)]
bar: String,
#[tia("Sushi",g*="tuna",s*="avocado")] // <- `g` and `s`: Sushi trait
baz: u8
}
fn main()
{
let mut mys = MyStruct::default();
mys.set_foo(123);
mys.set_bar("meow");
let foo_gettable = &mys as &dyn FooGettable<i32>;
let fruit = &mys as &dyn Fruit;
println!("{}, {}", foo_gettable.get_foo(), fruit.get_bar() );
let sushi = &mut mys as &mut dyn Sushi;
sushi.avocado(32);
println!("{}", sushi.tuna());
}
Then cargo run
:
123, meow
32
The generated code with print
, file
or file-pretty
features:
impl FooGettable<i32> for MyStruct
{
fn get_foo(&self) -> i32
{
self.foo
}
}
impl MyStruct
{
pub fn set_bar<T: Into<String>>(&mut self, v: T)
{
self.bar = v.into();
}
pub fn set_foo(&mut self, v: i32)
{
self.foo = v;
}
}
impl Fruit for MyStruct
{
fn get_bar(&self) -> &String
{
&self.bar
}
}
impl Sushi for MyStruct
{
fn avocado(&mut self, v: u8)
{
self.baz = v;
}
fn tuna(&self) -> u8
{
self.baz
}
}
tia="*"
in [dependencies]
section of the project Cargo.toml
file. ( Or I like cargo add tia
via cargo-edit )
file-pretty
features is good tool for your debugging. Read the bottom section "features" if you want.#[derive(Tia)]
proc-macro on head of your struct|enum|union.#[tia(...)]
proc-macro below the #[derive(Tia)]
(for struct|enum|union-level settings) or top of the specific fields.
...
is explanate in the next section "tia directives".tia
's proc-macro can parse the pattern:
#[tia( $tia_directive_0, $tia_directive_1,$tia_directive_2, ... )]
And the $tia_directive
pattern:
gm
=> ([g]et [m]ove
) ⚠ Move ⚠ pattern, it is NOT use for casually; like fn (self) -> i32 { self.value }
g
=> ([g]et
) For Copy
-able values, for use a primitive types such as u8
, f32
or a impl Copy
-ed types; like return &self.value
.rg
=> ([r]eference [g]et
) Return a reference &
pattern. It can be use in casually for most situations.rmg
=> ([r]eference [m]ut [g]et
) Return a reference mutable &mut
. Sometimes useful, and sometimes so complex and difficult.s
=> ([s]et
) Raw value move pattern.rs
=> ([r]eference [s]et
) Reference &
pattern, for Copy
-able types.rsc
=> ([r]eference [s]et [c]lone
) Clone
pattern, for Clone
-able types such as String
. This pattern require the same type for the input.rsi
=> ([r]eference [s]et [i]nto
) Into
pattern, for Into
-able types such as String
. This pattern could be type conversions. For eg, &str
|String
|&String
and more types are input to String
with this pattern.g
, rg
rgi
) => Getters are same as the Prefix with "get", Setters are same as the Prefix with "set".g="my_awesome_prefix"
=> Prefix with specialized prefix-part string pattern. It will be generate fn my_awesome_prefix_xxxx
for xxxx
field symbol.g+="my_awesome_suffix"
=> Suffix with specialized suffix-part string pattern. It will be generate fn xxxx_my_awesome_suffix
for xxxx
field symbol.g*="my_awesome_fullname"
=> Fullname pattern. It will be generate fn my_awesome_fullname
for a field.impl for MyStruct
codes for a fields."TraitSymbol"
=> It will be generate impl TraitSymbol for MyStruct
codes for a fields that appear in the after of this directive.""
=> It will be generate impl for MyStruct
codes for a fields that appear in the after of this directive.disable
Usage example:
[dependencies]
tia={ version="*", features=["disable"] }
tia
will be output nothing.tia
is not removed, thus it allow the #[derive(Tia)]
and #[tia(...)]
proc-macros with no effects.print
Usage example:
[dependencies]
tia={ version="*", features=["print"] }
tia
will be output the generated code to STDERR.
file-pretty
is better for human eyes.file
|file-pretty
Usage example:
[dependencies]
tia={ version="*", features=["file-pretty"] }
tia
will be output/update the generated code to the file such as src/.tia/MyStruct.rs
.What's the difference of file
and file-pretty
:
file
will be output the raw generated code. It is very compressed.file-pretty
will be output the raw generated code, and then apply rustfmt
automatically.
rustfmt
command in your development environment. (It is not a lib crate dependency.)include
|include-pretty
|include-force
Usage example:
[dependencies]
tia={ version="*", features=["include-pretty"] }
tia
will be:
include!(...)
macro such as include!("src/.tia/MyStruct")
instead.What's the difference of include
, include-pretty
and include-force
:
include
will be generate (=file
) code if the generated code is not found.include-pretty
will be generate and prettify (=file-pretty
) if the generated code is not found.include-force
will not be generate if the generated code is not found, maybe build will stop with an error(s).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.
Thank you!😍