# derive_destructure2 **(no-std)**

[![Rust](https://github.com/NobodyXu/derive_destructure2/actions/workflows/rust.yml/badge.svg)](https://github.com/NobodyXu/derive_destructure2/actions/workflows/rust.yml)

[![crate.io downloads](https://img.shields.io/crates/d/derive_destructure2)](https://crates.io/crates/derive_destructure2)

[![crate.io version](https://img.shields.io/crates/v/derive_destructure2)](https://crates.io/crates/derive_destructure2)

[![docs](https://docs.rs/derive_destructure2/badge.svg)](https://docs.rs/derive_destructure2)

**[examples](https://docs.rs/derive_destructure2_examples)**

This crate allows you to destructure structs that implement `Drop`.

If you've ever struggled with error E0509
"cannot move out of type `T`, which implements the `Drop` trait"
then this crate may be for you.

To use this crate, put this in your `lib.rs` or `main.rs` for rust < 1.30:

```ignore
#[macro_use]
extern crate derive_destructure2;
```

For rust >= 1.30, just import it as a regular item:

```ignore
use derive_destructure2::{destructure, remove_trait_impls};
```

Then you have 2 ways to use this crate:

## Option 1: `#[derive(destructure)]`

If you mark a struct with `#[derive(destructure)]`, then you can destructure it using
from your crate

```rust
let (field_1, field_2, ...) = my_struct.destructure();
```

This turns the struct into a tuple of its fields **without running the struct's `drop()`
method**. You can then happily move elements out of this tuple.

Note: in Rust, a tuple of 1 element is denoted as `(x,)`, not `(x)`.

__**`destructure` is implemented as a private associated function.**__

## Option 2: `#[derive(remove_trait_impls)]`

If you mark your struct with `#[derive(remove_trait_impls)]`, then you can do
from your crate

```rust
let my_struct = my_struct.remove_trait_impls();
```

The result is a struct with the same fields, but it implements no traits
(except automatically-implemented traits like `Sync` and `Send`).
In particular, it doesn't implement `Drop`, so you can move fields out of it.

The name of the resulting struct is the original name plus the suffix
`WithoutTraitImpls`.

For example, `Foo` becomes `FooWithoutTraitImpls`. But you usually don't need to write
out this name.

`#[derive(remove_trait_impls)]` works on enums too.

__**`remove_trait_impls` is a private associated function.**__

## Example:

```rust
use derive_destructure2::*;

#[derive(destructure, remove_trait_impls)]
struct ImplementsDrop {
    some_str: String,
    some_int: i32
}

impl Drop for ImplementsDrop {
    fn drop(&mut self) {
        panic!("We don't want to drop this");
    }
}

fn main() {
    // Using destructure():
    let x = ImplementsDrop {
        some_str: "foo".to_owned(),
        some_int: 4
    };
    let (some_str, some_int) = x.destructure();
    // x's drop() method never gets called

    // Using remove_trait_impls():
    let x = ImplementsDrop {
        some_str: "foo".to_owned(),
        some_int: 4
    };
    let x = x.remove_trait_impls();
    // this x doesn't implement drop,
    // so we can move fields out of it
    drop(x.some_str);
    println!("{}", x.some_int);
}
```

## License

Licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.
