hexga_map_on 0.0.11-beta.2

Define the map_on! macro that can be used to impl a lot of trait quickly using macros.
Documentation
## HexGa Map On


Define the `map_on!` macro that can be used to impl a lot of trait quickly using macros
You can have a finer control about what you want to impl :

```rust
use hexga_map_on::prelude::*;

trait MinusOne
{
    const MINUS_ONE : Self;
}

map_on!
(
    (
        i8, i16, i32, i64, isize,
        f32, f64
    ), 
    ($name:ident) => 
    {
        impl MinusOne for $name
        {
            const MINUS_ONE : Self = -1 as Self;
        }
    }
);
```

Some variation of `map_on` exist for different use case :

```rust
use hexga_map_on::prelude::*;

trait Zero
{
    const ZERO : Self;
}

map_on_number!(
    ($name:ident) => 
    {
        impl Zero for $name
        {
            const ZERO : Self = 0 as Self;
        }
    }
);
```

Available `map_on!` macro :

- `map_on!`
- `map_on_integer_unsigned!` : `u8`, `u16`, `u32`, `u64`, `usize`
- `map_on_integer_signed!` : `i8`, `i16`, `i32`, `i64`, `isize`
- `map_on_integer` : (`u8`, `u16`, `u32`, `u64`, `usize`) + (`i8`, `i16`, `i32`, `i64`, `isize`)
- `map_on_float!` : `f32`, `f64`
- `map_on_number!` : (`u8`, `u16`, `u32`, `u64`, `usize`) + (`i8`, `i16`, `i32`, `i64`, `isize`) + (`f32`, `f64`)
- `map_on_number_and_bool!` : (`u8`, `u16`, `u32`, `u64`, `usize`) + (`i8`, `i16`, `i32`, `i64`, `isize`) + (`f32`, `f64`) + (`bool`)

- `map_on_operator_binary_arithmetic_unit` : `Add`, `Sub`
- `map_on_operator_binary_arithmetic` : (`Add`, `Sub`) + (`Mul`, `Div`, `Rem`)
- `map_on_operator_binary_bit` : `BitOr`, `BitAnd`, `Shl`, `Shr`
- `map_on_operator_binary` : (`Add`, `Sub`) + (`Mul`, `Div`, `Rem`) + (`BitOr`, `BitAnd`, `Shl`, `Shr`)

- `map_on_operator_assign_arithmetic_unit` : `AddAssign`, `SubAssign`
- `map_on_operator_assign_arithmetic` : (`AddAssign`, `SubAssign`) + (`MulAssign`, `DivAssign`, `RemAssign`)
- `map_on_operator_assign_bit` : `BitOrAssign`, `BitAndAssign`, `ShlAssign`, `ShrAssign`
- `map_on_operator_assign` : (`AddAssign`, `SubAssign`) + (`MulAssign`, `DivAssign`, `RemAssign`) + (`BitOrAssign`, `BitAndAssign`, `ShlAssign`, `ShrAssign`)

- `map_on_operator_unary_bit` : `Not`
- `map_on_operator_unary_arithmetic_unit` : `Neg`, `Abs` (Note : `Abs` should be a user defined trait, currently there isn't such a operator on the standard lib)
- `map_on_operator_unary` : (`Not`) + (`Neg`, `Abs`)

## More Example


You can also use the `map_on!` macro to call another macro :

```rust
use hexga_map_on::prelude::*;

trait One
{
    const ONE : Self;
}

macro_rules! impl_one {
    ($type_name:ty) => {
        impl One for $type_name
        {
            const ONE : Self = 1 as Self;
        }
    };
}

map_on_number!(impl_one);
```

It is also possible to use nested `map_on!`*1 macro (only when using macro name, or in const context like implementing a trait) :

```rust
use hexga_map_on::prelude::*;

pub trait CastInto<T>
{
    /// Might lose some precision.
    /// Same semantics as the [as](https://practice.course.rs/type-conversions/as.html) keyword: `4f32 as u64`
    fn cast_to(self) -> T;
}

// Double recursive macro :)
macro_rules! impl_cast_to 
{ 
    ($itself: ty, $cast_into: ty) => 
    { 
        impl CastInto<$cast_into> for $itself
        {
            fn cast_to(self) -> $cast_into { self as _ }
        }
    }; 

    ($cast_into: ty) => 
    {
        map_on_number!(impl_cast_to,$cast_into);
    }; 
}
// Do 144 trait impl in a few lines :) 
map_on_number!(impl_cast_to);

fn main()
{
    assert_eq!(20.5f32 as i8, 20.5f32.cast_to());
    assert_eq!(4.5 as u32, 4.5.cast_to());
    assert_eq!(4u8 as i64, 4u8.cast_to());
}
```

Implementing a binary operator is also possible :

```rust
use hexga_map_on::prelude::*;

#[derive(Debug)]

struct X(pub i32);

map_on_operator_binary!(
    (($trait_name: tt, $fn_name: tt)) => 
    {
        impl std::ops::$trait_name for X
        {
            type Output = X;
            fn $fn_name(self, rhs : Self) -> Self::Output { X(self.0.$fn_name(rhs.0)) }
        }
    }
);

fn main() 
{
    let x =         X(9) + X(3) * X(4) / X(2);
    assert_eq!(x.0,   9  +   3  *   4  /   2 );
}
```

## Limitation


Right now it is impossible to use the `map_on!` macro in a non const context (like in a function body) with lambda syntax.

```rust
macro_rules! print_type {
    ($type_name:ty) => {
        println!("print type from macro name {}", ::std::any::type_name::<$type_name>());
    };
}

fn main() 
{
    // work fine
    map_on!((f32, f64), print_type); 

    // Don't work :/
    map_on!((f32, f64),
        ($type_name:ident) => 
        {
            println!("print type from macro lambda {}", ::std::any::type_name::<$type_name>());
        }
    );
}
```

The reason is that the lambda macro form will create a temporary macro with the name `__map_on_inliner`.
Because nested lambda map_on! macro call will generate a new macro each time with the same name `__map_on_inliner`, it will conflict with the previous one.
So we need a mecansime to scope the macro name.

Right now the only way to do that that I know is to use a `const` block, which is not ideal because it limit where the macro can be used : in a const context.

```rust
const _: () = {
    // definitions, trait impls, etc…
};
```
<https://internals.rust-lang.org/t/anonymous-modules/15441/2?u=thomas-mewily>

The definiton for lambda `map_on!` macro is the following :

```rust
($tokens:tt, $($macro_arms:tt)+) => {
    const _: () = {
        macro_rules! __map_on_inliner {
            $($macro_arms)+
        }

        $crate::map_on!(@expand_tokens $tokens);
    };
};
```