[![crates.io](https://img.shields.io/crates/v/nest_struct.svg)](https://crates.io/crates/nest_struct)
[![docs.rs](https://img.shields.io/docsrs/nest_struct.svg)](https://docs.rs/nest_struct)
[![CI](https://github.com/ZibanPirate/nest_struct/actions/workflows/ci.yml/badge.svg)](https://github.com/ZibanPirate/nest_struct/actions/workflows/ci.yml)
[![Maintenance](https://img.shields.io/badge/maintenance-actively--developed-brightgreen.svg)](https://github.com/ZibanPirate/nest_struct/commits/main/)
# nest_struct
Nest struct and enum definitions with minimal syntax changes in Rust
### Example
```rust
use nest_struct::nest_struct;
#[nest_struct]
struct Post {
title: String,
summary: String,
author: nest! {
name: String,
handle: String,
},
}
```
See expanded code
```rust
struct Post {
title: String,
summary: String,
author: PostAuthor,
}
struct PostAuthor {
name: String,
handle: String,
}
```
You can also overwrite inner struct name, by passing the name itself as macro instead of `nest!`:
```rust
use nest_struct::nest_struct;
#[nest_struct]
struct Post {
title: String,
summary: String,
author: Author! {
name: String,
handle: String,
},
}
```
See expanded code
```rust
struct Post {
title: String,
summary: String,
author: Author,
}
struct Author {
name: String,
handle: String,
}
```
Or, you can open a block and define struct like normal Rust code for full flexibility:
```rust
use nest_struct::nest_struct;
#[nest_struct]
struct Post {
title: String,
summary: String,
author: nest! {
/// doc comment for Author struct
#[derive(Debug)]
struct Author {
name: String,
handle: String,
}
},
}
```
See expanded code
```rust
struct Post {
title: String,
summary: String,
author: Author,
}
/// doc comment for Author struct
#[derive(Debug)]
struct Author {
name: String,
handle: String,
}
```
Another example calling Pokemon API
```rust
use nest_struct::nest_struct;
// Define a struct with nested struct definitions all in one place
// with minimal syntax changes.
#[nest_struct]
#[derive(serde::Deserialize)]
struct APIResponse {
id: u32,
name: String,
abilities: Vec,
}
let body = reqwest::blocking::get("https://pokeapi.co/api/v2/pokemon/ditto").unwrap().text().unwrap();
let api_response: APIResponse = serde_json::from_str(&body).unwrap();
assert_eq!(api_response.name, "ditto");
// Access nested struct fields
assert_eq!(api_response.abilities.first().unwrap().ability.name, "limber");
```
For more examples, see the [`./tests/cases`](https://github.com/ZibanPirate/nest_struct/tree/main/tests/cases) directory.
### Features
- [x] deep nesting (no theoretical limit).
- [x] nest `struct` inside another `struct`.
- [x] nest `enum` inside another `enum`.
- [x] nest `enum` inside a `struct` and vice-versa.
- [x] inherit `derive` and other attribute macros from root `struct`.
- [x] auto-generate inner `struct` names.
- [x] overwrite the auto-generated inner struct name.
Feature parity with native Rust code:
- [x] `impl` block on inner `struct`s.
- [x] define `derive` and other attribute macros individually per inner `struct`.
- [x] define doc comments individually per inner `struct`.
- [ ] useful compiler error messages.
- [x] support generic types.
- [x] support lifetimes.
## Contributing
Contributions are welcome, please read [`CONTRIBUTING.md`](https://github.com/ZibanPirate/nest_struct/blob/main/CONTRIBUTING.md) to get started.
## License
Licensed under MIT (twitter: [@zibanpirate](https://twitter.com/zibanpirate)).