#anonymous-struct #multiple-return

macro atruct

macros for anonymous structs in Rust

11 releases

Uses new Rust 2021

0.3.2 Nov 9, 2022
0.3.1 Nov 9, 2022
0.2.4 Oct 24, 2022
0.1.3 Oct 15, 2022

#394 in Rust patterns

Download history 136/week @ 2022-10-15 69/week @ 2022-10-22 10/week @ 2022-10-29 77/week @ 2022-11-05 18/week @ 2022-11-12 3/week @ 2022-11-19 3/week @ 2022-11-26

109 downloads per month

MIT license

30KB
648 lines

Current atruct provides following 3 macros related to anonymous struct:

  • atruct!
  • #[Return]
  • #[withReturn]


atruct!

inspired by structx (that doesn't work now), atruct! macro enables to use variables of anonymous structs like

use atruct::atruct;

fn main() {
    let anonymous = atruct!(
        // Type annotaion is needed for each non-literal value.
        // There are 2 options to annotate type:

        string1 @ String: String::from("string1"),  // @ pattern and
        string2(String): String::from("string2"),  // () pattern.
        // Their behaviors are completely the same. Use any one you like!

        box_option_vec @ Box<Option<Vec<u8>>>: Box::new(Some(Vec::new())),
        vec(Vec<u8>): vec![0, 1, 0, 1, 1],

        nest: {
            a: "you can define nested struct without prepare lots of named structs",
            b: 100usize,  // literals don't need type annotation
        },
    );

    println!("{}", anonymous.string1);  // string1
    println!("{}", anonymous.string2);  // string2
    println!("{:?}", anonymous.box_option_vec);  // Some([])
    println!("{:?}", anonymous.vec);  // [0, 1, 0, 1, 1]
    println!("{}", anonymous.nest.a)  // you can define nested struct without prepare lots of named structs
}

( examples/struct_of_various_values.rs )


  • atruct! supports nested structs.

  • When atruct was v0.1 only literals are supported as values, BUT in v0.2 you can use (maybe) any type of values!



#[Return]

We usually return more than 1 values from a function. In such situations, Rust supports only tupple as a way to bundle returned values. But it's sometimes a bit anoying: when we'd like to name freely to each field, not 0, 1, 2, ...

#[Return] attribute enables such naming. You can write functions like

use atruct::Return;

fn main() {
    let abc = get_abc();
    println!("{}", abc.a);  // 24
    println!("{}", abc.b);  // you can use any value in a field
    println!("{:?}", abc.c);  // [-1, 0, 0, -1, 1, 0, 1, -1]
}

#[Return(a: u8, b: String, c: Vec<isize>)]  // not supporting nest
fn get_abc() {
    Return {
        a: 24,
        b: "you can use any value in a field".into(),
        c: vec![-1,0,0,-1,1,0,1,-1],
    }
}

( examples/return_struct.rs )


  • #[Return] doesn't support nested structs. So returned value is just like a tupple you can give any names to its fields.
  • #[Return] automatically generates a struct named as "FunctionName" ( e.g. if function is get_abc, for example, GetAbc ), but at the same time defines a type synonym Return. So you DON't need to memorize the generated struct's name.


#[withReturn]

Actually, #[Return] itself is NOT available in impl block for a technical reason. #[withReturn] enables this:

use atruct::withReturn;

fn main() {
    let abc = T::get_abc();
    println!("abc: {{a: {}, b: {}, c: {:?}}}", abc.a, abc.b, abc.c);
    // abc: {a: 0, b: I am b, c: [1, 0, -1, 0]}
}

struct T;
#[withReturn]
impl T {
    #[Return(a: u8, b: String, c: Vec<isize>)]
    fn get_abc() {
        Return {
            a: 0,
            b: "I am b".into(),
            c: vec![1, 0, -1, 0],
        }
    }
}

( examples/return_in_impl_block.rs )


  • As you see, you don't need to use atruct::Return just to write #[Return] in impl blocks.
  • Current #[withReturn] generates structs in completely the same way as normal #[Return], meaning all functions using #[Return] have to have unique names to each others (This problem will be fixed in a few days).

Dependencies

~210–610KB
~15K SLoC