The Newtype trait

Build Status Latest Version Rust Documentation GitHub license

The Problem

Sometimes you want to wrap a type in a newtype, but you want the newtype implements the same traits as the wrapped type. The Newtype trait helps you to implement the traits of the wrapped type for the newtype automatically.

The Solution

When you define a trait, you can support the Newtype trait and any type that implements the Newtype trait will automatically implement your trait.

```rust use thenewtype::Newtype; use derivemore::AsRef;

pub trait MyTrait { fn my_method(&self) -> String; }

impl MyTrait for T where T: Newtype + AsRef, T::Inner: MyTrait, { fn mymethod(&self) -> String { self.asref().my_method() } }

// Now we can use the MyTrait trait for the newtype.

struct Foo;

impl MyTrait for Foo { fn mymethod(&self) -> String { "foo".tostring() } }

[derive(AsRef)]

struct Bar(Foo);

impl Newtype for Bar { type Inner = Foo; }

fn main() { let bar = Bar(Foo); asserteq!(bar.mymethod(), "foo"); } ```

When to use

You can use the Newtype trait when you want to wrap a type in a newtype and you want the newtype implements ALL the newtype-supported traits of the wrapped type. If you need some traits, you should implement them manually and avoid using the Newtype trait.

Drawbacks

The Newtype trait is not a good solution for the following cases:

```rust use the_newtype::Newtype;

trait Fancy { fn fancy_method(&self) -> String; }

// it's ok to implement the Fancy trait for the Newtype trait

impl Fancy for T where T: Newtype + AsRef, T::Inner: Fancy, { fn fancymethod(&self) -> String { self.asref().fancy_method() } }

trait Awesome { fn awesome_method(&self) -> String; }

// every type that implements the Fancy trait will implement the Awesome trait // it's not possible to implement the Awesome trait for the Newtype trait

impl Awesome for T where T: Fancy, { fn awesomemethod(&self) -> String { let fancy = self.fancymethod(); format!("{} is awesome!", fancy) } }

```

Tips

Use derive_more and Newtype macros

You can use the derive_more crate to implement the AsRef, AsMut, and Into traits for the newtype. And you can use the Newtype macro to implement the Newtype trait for the newtype.

```rust use thenewtype::Newtype; use derivemore::AsRef;

[derive(AsRef, Newtype)]

struct Bar(String); ```

How to implement a trait for &self

If you want to implement a trait for &self, you can use the AsRef trait.

```rust use the_newtype::Newtype;

trait MyTrait { fn my_method(&self) -> String; }

impl MyTrait for T where T: Newtype + AsRef, T::Inner: MyTrait, { fn mymethod(&self) -> String { self.asref().my_method() } } ```

How to implement a trait for &mut self

If you want to implement a trait for &mut self, you can use the AsMut trait.

```rust use the_newtype::Newtype;

trait MyTrait { fn my_method(&mut self) -> String; }

impl MyTrait for T where T: Newtype + AsMut, T::Inner: MyTrait, { fn mymethod(&mut self) -> String { self.asmut().my_method() } } ```

How to implement a trait for self

If you want to implement a trait for self, you can use the Into trait.

```rust use the_newtype::Newtype;

trait MyTrait { fn my_method(self) -> String; }

impl MyTrait for T where T: Newtype + Into, T::Inner: MyTrait, { fn mymethod(self) -> String { self.into().mymethod() } } ```

How to implement a trait without self

If you want to implement a trait without self, no extra trait is needed.

```rust use the_newtype::Newtype;

trait MyTrait { fn my_method() -> String; }

impl MyTrait for T where T: Newtype, T::Inner: MyTrait, { fn mymethod() -> String { T::Inner::mymethod() } } ```

How to combine self, &self or &mut self

If you want to implement a trait for self, &self or &mut self, you can use the Into, AsRef or AsMut traits together.

```rust use the_newtype::Newtype;

trait MyTrait { fn mymethod(&self) -> String; fn mymethod_mut(&mut self) -> String; }

impl MyTrait for T where T: Newtype + AsRef + AsMut, T::Inner: MyTrait, { fn mymethod(&self) -> String { self.asref().my_method() }

fn my_method_mut(&mut self) -> String {
    self.as_mut().my_method_mut()
}

} ```

Installation

toml [dependencies] the-newtype = "0.1"