# 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.