Skip to content

Commit

Permalink
Add field-specific functionality to Into (#291)
Browse files Browse the repository at this point in the history
Resolves #287 

Allow using the same attribute arguments on fields as on the whole
struct, generate `impl`s for each

Co-authored-by: tyranron <tyranron@gmail.com>
  • Loading branch information
MegaBluejay and tyranron committed Oct 19, 2023
1 parent 81660fc commit 50ae43b
Show file tree
Hide file tree
Showing 9 changed files with 827 additions and 100 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
and ignores field type itself.
- The `Into` derive now uses `#[into(<types>)]` instead of `#[into(types(<types>))]`
and ignores field type itself.
- The `Into` derive now generates separate impls for each field whenever the `#[into(...)]`
attribute is applied to it. ([#291](https://github.com/JelteF/derive_more/pull/291))
- Importing a derive macro now also import its corresponding trait.
- The `Error` derive is updated with changes to the `error_generic_member_access`
unstable feature for nightly users. ([#200](https://github.com/JelteF/derive_more/pull/200),
Expand Down
84 changes: 84 additions & 0 deletions impl/doc/into.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,90 @@ assert_eq!(5_i128, Mass::<Gram>::new(5).into());
```


### Fields

The `#[into]` attribute can also be applied to specific fields of a struct.

```rust
# use derive_more::Into;
#
#[derive(Into)]
struct Data {
id: i32,
#[into]
raw: f64
}

assert_eq!(42.0, Data { id: 1, raw: 42.0 }.into());
```

In such cases, no conversion into a tuple of all fields is generated, unless
an explicit struct attribute is present.

```rust
# use derive_more::Into;
#
#[derive(Into)]
#[into]
struct Data {
id: i32,
#[into]
raw: f64
}

assert_eq!(42.0, Data { id: 1, raw: 42.0 }.into());
assert_eq!((1, 42.0), Data { id: 1, raw: 42.0 }.into());
```

The `#[into(<types>)]` syntax can be used on fields as well.

```rust
# use std::marker::PhantomData;
# use derive_more::Into;
# struct Whatever;
#
#[derive(Into, Clone)]
#[into(owned, ref((u8, str)), ref_mut)]
struct Foo {
#[into(owned(u64), ref)]
a: u8,
b: String,
#[into(skip)]
_c: PhantomData<Whatever>,
}

let mut foo = Foo { a: 1, b: "string".to_owned(), _c: PhantomData };

assert_eq!((1_u8, "string".to_owned()), foo.clone().into());
assert_eq!((&1_u8, "string"), <(&u8, &str)>::from(&foo));
assert_eq!((&mut 1_u8, &mut "string".to_owned()), <(&mut u8, &mut String)>::from(&mut foo));
assert_eq!(1_u64, foo.clone().into());
assert_eq!(&1_u8, <&u8>::from(&foo));
```

Fields, having specific conversions into them, can also be skipped for top-level
tuple conversions.

```rust
# use derive_more::Into;

#[derive(Into)]
#[into(ref((str, f64)))]
struct Foo {
#[into(ref)]
#[into(skip)]
a: u8,
b: String,
c: f64,
}

let foo = Foo { a: 1, b: "string".to_owned(), c: 3.0 };

assert_eq!(("string", &3.0), (&foo).into());
assert_eq!(&1_u8, <&u8>::from(&foo));
```




## Enums
Expand Down
Loading

0 comments on commit 50ae43b

Please sign in to comment.