#derive #into #owned #procedural-macros #cow

macro derive-into-owned

Custom derives to help with types containing Cow fields

2 unstable releases

Uses new Rust 2021

0.2.0 Jan 8, 2022
0.1.0 May 30, 2017

#375 in Rust patterns

Download history 7664/week @ 2021-09-28 31758/week @ 2021-10-05 21530/week @ 2021-10-12 10765/week @ 2021-10-19 10612/week @ 2021-10-26 12951/week @ 2021-11-02 13103/week @ 2021-11-09 5304/week @ 2021-11-16 1517/week @ 2021-11-23 1786/week @ 2021-11-30 1510/week @ 2021-12-07 1759/week @ 2021-12-14 862/week @ 2021-12-21 392/week @ 2021-12-28 1163/week @ 2022-01-04 938/week @ 2022-01-11

3,532 downloads per month
Used in 15 crates (3 directly)

MIT license

26KB
481 lines

derive-into-owned

Build Status crates.io docs.rs

Rust procedural macros for deriving methods to help with working with types that contain Cow fields. Please note that this derive somewhat strangely works with duck-typing, at least for now. It was originally created to help me reduce the boilerplate with Cow types.

[derive(IntoOwned)] generates a method similar to:

use std::borrow::Cow;

struct Foo<'a> {
	field: Cow<'a, str>,
}

impl<'a> Foo<'a> {
	/// This method would be derived using #[derive(IntoOwned)]
	pub fn into_owned(self) -> Foo<'static> {
		Foo {
			field: Cow::Owned(self.field.into_owned()),
		}
	}
}

Originally based off of deep-clone-derive example but supports:

But wait there is even more! [derive(Borrowed)] generates a currently perhaps a bit limited version of a method like:

impl<'a> Foo<'a> {
	pub fn borrowed<'b>(&'b self) -> Foo<'b> {
		Foo {
			field: Cow::Borrowed(self.field.as_ref()),
		}
	}
}

Types with lifetimes

If your struct has a field with type Bar<'a> then Bar is assumed to have a method fn into_owned(self) -> Bar<'static>.

Note, there's no trait implementation expected because I didn't find one at the time and didn't think to create my own, assumed the Cow::into_owned might be getting an extension in standard library which never happened and so on.

Limitations

Currently deriving will fail miserably for at least but not limited to:

  • IntoOwned: borrowed fields like &'a str
  • Borrowed: struct/enum has more than one lifetime
  • both: arrays not supported
  • both: into_owned/borrowed types inside tuples inside vectors

Using with incompatible types results in not so understandable error messages. For example, given a struct:

#[derive(IntoOwned)]
struct Foo<'a> {
	field: &'a str,
}

The compiler error will be:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 4:10...
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
  = note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected Foo<'static>, found Foo<'_>)
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
error: aborting due to previous error(s)

Dependencies

~285–700KB
~17K SLoC