tia 1.0.0

tia; trait, impl, accessors | automatic
Documentation

tia; trait, impl accessors | automatic

This is a syntax sugar proc-macro crate for trait, impl accessors patterns. tia generate to an accessor impls of an indivisual traits for any struct|enun|unions.

Features

  • tia will be generate impl codes automatically if you set the #[tia(...)] directives.
  • Target types: struct | enum | union
  • Setting levels: for all fields | per field
  • trait supporting: Can be generate for multiple traits.
    • #[tia(MyTrait1: rg, MyTrait2: si)] (See also the Example-3 in below.)
  • Generative accessors: Getter-like, Setter-like
    • gm for get/move pattern; for move-semantics tunings.
    • g for get/implicit copy pattern; for primitive types such as u8.
    • rg for get/reference pattern; for reference usages. (See also the Example-1 in below.)
    • rmg for get/reference mut pattern; for r/w as object.
    • s for set/implicit move/copy pattern; for primitive types such as u8 and Copy-ables.
    • rs for set/explicit copy with Clone::clone_from pattern; for Clone-able without type converting.
    • rsi for set/explicit copy with Into::into pattern; for Into-able input types with type converting if required.
  • Useful +features:
    • print, show a generated codes in building-time via stdcerr.
    • file, output a generated codes to files such as src/.tia/{MyStructSymbol}.rs.
    • file-pretty, file + formatting with rustfmt command.
    • disable, disable all tia features in temporary.
  • Naming patters:
    • Default, will generate a get_xxxx | set_xxxx prefixed accessor.
    • Spedified prefix, rg="awesome", will generate awesome_xxxx prefixed accessor.
    • Spedified suffix, rg+="awesome", will generate xxxx_awesome suffixed accessor.
    • Fullname, rg="awesome" will generate awesome fullname defined accessor.

Example

Example-1; The introduction of tia

It is minimal, very simple version. Without traits 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
  • (1,2) are preparing.
  • (3) is tia directive for the struct-level.
  • (4,5) are an automatic generated accessors by 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"] }

Example-2; A little complex/practical usage

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 = []

Example-3; trait usage

use 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
 }
}

Example-4; Misc.

The include feature:

[dependencies]
tia={ version="*", features=["file-pretty","include"] }

tia will be:

  1. Generate codes if not exists.
  2. Generate include! such as include!("src/.tia/MyStruct") instead.

Note

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.

LICENSE

Author