attrimpl 0.5.0

The crate provides attributes to automatically implement common traits and reduce boilerplate code.
Documentation
# Warning
This package is under construction, handle with care!


# attrimpl
The aim of the package is to reduce boilerplate code by adding implementations in trivial cases.


## Directives
Directives that can be added before fields
- `from`: implements `From` trait for the given type
- `into`: implements `Into` trait for the given type
- `convert`: adds both `from` and `into` directives for the given field
- `deref`: implements `Deref` trait for the given type
- `deref_mut`: implements `Deref` and `DerefMut` traits for the given type
- `as_ref`: implements `AsRef` trait for the given type
- `as_mut`: implements `AsMut` trait for the given type
- `as`: adds both `as_ref` and `as_mut` directives for the given field
- `get_ref`: adds a getter method for the field, a reference is returned
  - accepted params
    - `name`: specifies the name of the getter function, default value is `<field_name>` (e.g., `get_ref(name = "foobar")`)
- `get_clone`: adds a getter method for the field, the value is cloned
  - accepted params
    - `name`: specifies the name of the getter function, default value is `<field_name>` (e.g., `get_clone(name = "foobar")`)
- `get_copy`: adds a getter method for the field, the value is copied
  - accepted params
    - `name`: specifies the name of the getter function, default value is `<field_name>` (e.g., `get_copy(name = "foobar")`)
- `get_mut`: adds a mutable getter method for the field
  - accepted params
    - `name`: specifies the name of the getter function (`<name>_mut`), default value is `<field_name>_mut` (e.g., `get_mut(name = "foobar")`)
- `access`: adds both `get_ref` and `get_mut` directives for the given field
  - accepted params
    - `name`: specifies the name of both the getter and the get_mut function (e.g., `access(name = "foobar")`)
    - `get_ref`: specifies the type of the getter function, this is the default
    - `get_clone`: specifies the type of the getter function
    - `get_copy`: specifies the type of the getter function


## Debugging
If the `debug` argument is added to the macro, then the generated code will be printed to stderr during compilation. Example:
```rust
#[attrimpl::attrimpl(debug)]
struct NamedStruct {
    #[attrimpl(from, into, deref_mut)]
    name: String,
}
```


## Examples
**Named struct (from, into, deref_mut):**
```rust
#[attrimpl::attrimpl]
struct NamedStruct {
    #[attrimpl(from, into, deref_mut)]
    name: String,
}

// non-boxed
let mut value = NamedStruct::from("test".to_string());
value.push_str("ing");
let value: String = value.into();

// boxed
let mut value = Box::<NamedStruct>::from("test".to_string());
value.push_str("ing");
let value: String = (*value).into();
```

**Named struct (into, as_ref, as_mut, get_ref, get_mut):**
```rust
#[attrimpl::attrimpl]
struct NamedStruct {
    #[attrimpl(into)]
    #[attrimpl(as_ref, as_mut)]
    #[attrimpl(get_ref)]
    name: String,

    #[attrimpl(deref_mut)]
    #[attrimpl(access(name = "hobbyy"))]
    hobby: String,
}

let mut value = NamedStruct {
    name: "Jane Doe".to_string(),
    hobby: "rock climbing".to_string(),
};

// deref_mut
*value = "ice climbing".to_string();
// deref
assert_eq!(*value, "ice climbing");

// access(name = "hobbyy")
*value.hobbyy_mut() = "rock climbing".to_string();
assert_eq!(value.hobbyy(), "rock climbing");

// get_ref
assert_eq!(value.name(), "Jane Doe");

// as_ref
assert_eq!(value.as_ref(), "Jane Doe");
// as_mut
*value.as_mut() = "John Doe".to_string();
assert_eq!(value.as_ref(), "John Doe");

// into
let value: String = value.into();
assert_eq!(value, "John Doe");
```

**Tuple struct:**
```rust
#[attrimpl::attrimpl]
struct TupleStruct1(#[attrimpl(from, into, deref_mut)] String);

// non-boxed
let mut value = TupleStruct1::from("test".to_string());
value.push_str("ing");
let value: String = value.into();

// boxed
let mut value = Box::<TupleStruct1>::from("test".to_string());
value.push_str("ing");
let value: String = (*value).into();
```

**Enum:**
```rust
#[attrimpl::attrimpl]
enum Enum {
    S(#[attrimpl(convert)] String),
    U8 {
        #[attrimpl(from)]
        byte: u8,
    },
    F64(#[attrimpl(convert)] f64),
}

// non-boxed
let value = Enum::from("test".to_string());

// boxed
let value = Box::<Enum>::from("test".to_string());
```


## Todo
* consider implementing `from_boxed` directive or (better) `from(boxed)`
  * 
  ```rust
    {
        // from Box<String>
        let value = NamedStruct::from(Box::new("test".to_string()));
        assert_eq!(value.name, "test");

        // Boxed from Box<String>
        let value = Box::<NamedStruct>::from(Box::new("test".to_string()));
        assert_eq!(value.name, "test");
    }
    {
        // into Box<String>
        // Boxed into String
        // Boxed into Box<String>
    }
  ```
* accept only valid directives during parsing for the given item type (e.g., for enums no Deref or DerefMut should be accepted) (better error handling)
* handle errors in the package instead of relying on the Rust compiler where possible
* examine whether it is possible to implement deref, deref_mut, into, as_ref, as_mut on enums if every variant contains the same type
* `#[attrimpl(from)]` should work with multiple field structs and enums. Should be able to set the default values of the other fields (e.g., `#[attrimpl(from(field_default | container_default))]`).
* write test framework for compile time errors
* write a failing test where non-defined directive is given
* implement the following directives
  * `#[attrimpl(display("asdasd {}"))]`
  * not sure whether to implement that one: #[attrimpl(borrow)]
  * search for other possibilities of useful directives