structout

Usage

This library allows for generating multiple structs from a single definition through a procedural macro.

generate!( <...> where ... { field: type, ... } => { OutputStruct => [action(arg), ...] } )

Where "actions" can be one of:

Put into practice:

```rust use structout::generate;

generate!( <> { foo: u32, bar: u64, baz: String } => { WithoutFoo => [omit(foo)], WithoutBar => [omit(bar)], } ); ```

The code above should expand to two structs

rust struct WithoutFoo { bar: u64, baz: String } struct WithoutBar { foo: u32, baz: String }


If one were to add two generic arguments, they should be efficiently split between the variants without the need for PhantomData.

rust generate!( <S, C> where S: Sized, C: Copy { foo: S, bar: G } => { OnlyBar => [omit(foo)], OnlyFoo => [omit(bar)], } );

The above code should expand to

rust struct OnlyBar<C> where C: Copy, { bar: G, } struct OnlyFoo<S> where S: Sized, { foo: S, }

For examples of usage for the full API, consult the tests module.

Development

Testing

Testing revolves around snapshot testing (insta). It's effectively done by running cargo expand (cargo-expand), getting its output, then reviewing with it with cargo insta review (cargo insta).

Consult the tests module for seeing how it's implemented in practice.

Motivation

This library attends to the need of generating multiple structs for a single definition. Consider the code

```rust struct Human { id: u32, age: u32, username: String, name: String, surname: String }

// suppose this is what you would get from an API struct HumanEditableParts { name: String, surname: String } ```

HumanEditableParts manually repeats some of the fields and those need to be kept in sync.

In Rust, it is said this pattern can be avoided with "struct composition". i.e.

```rust struct HumanEditableParts { name: String, surname: String1 }

struct Human { id: u32, age: u32, username: String, editable_parts: HumanEditableParts } ```

However, that is not always feasible, nor always pleasant to do.