Crate typle

source ·
Expand description

A proc macro to generate multiple items for tuples. Example code:

use typle::typle;

struct MyStruct<T> {
    pub t: T,
}

#[typle(Tuple for 1..=3)]
impl<T> MyStruct<T>
where
    T: Tuple(u32),
{
    fn max(&self) -> Option<u32> {
        let mut max = self.t[[0]];
        for typle_const!(i) in 1..T::LEN {
            if self.t[[i]] > max {
                max = self.t[[i]];
            }
        }
        Some(max)
    }
}

This code creates implementations for 1-, 2-, and 3-tuples where each component of the tuple is a u32.

impl MyStruct<(u32,)> {
    fn max(&self) -> Option<u32> {
        let mut max = self.t.0;
        {}
        Some(max)
    }
}
impl MyStruct<(u32, u32)> {
    fn max(&self) -> Option<u32> {
        let mut max = self.t.0;
        {
            {
                if self.t.1 > max {
                    max = self.t.1;
                }
            }
        }
        Some(max)
    }
}
impl MyStruct<(u32, u32, u32)> {
    fn max(&self) -> Option<u32> {
        let mut max = self.t.0;
        {
            {
                if self.t.1 > max {
                    max = self.t.1;
                }
            }
            {
                if self.t.2 > max {
                    max = self.t.2;
                }
            }
        }
        Some(max)
    }
}

The macro arguments Tuple for 1..=3 consist of an identifier (Tuple) to use as a pseudo-trait in the where clause, and a range of tuple lengths 1..=3 for which the item will be created.

The Tuple pseudo-trait is similar to a trait defined as

trait Tuple {
    const LEN: usize;
    type Types;
}

Tuple::LEN or T::LEN provides the number of components for the tuple in the current item.

If the where clause constrains a generic type using the pseudo-trait then the generic type must be a tuple with a length Tuple::LEN and where each component is constrained by the argument to the trait. The component can either be an explicit type (where T: Tuple(u32)) or can be constrained by other traits using the Types associated type:

impl<T> MyStruct<T>
where
    T: Tuple,
    T::Types: Extract,
    T::Types::Output: AsRef<str>,

Each component of the tuple must meet the type constraints for T::Types but the components can be different types. This is a special behavior for typles.

To force each component to be the same type, introduce an additional generic variable for the component type:

impl<T, C> MyStruct<T>
where
    T: Tuple(C),
    C: Extract,
    C::Output: AsRef<str>,

The components of a tuple can be iterated over using a for loop with an iteration variable enclosed in typle_const! macro. As shown above, this executes the for loop body for each component in the tuple.

Tuple components are referenced using a double-bracketed index and a constant value, including an index created using typle_const!. Hence self.t[[i]] will be replaced by self.t.0, self.t.1,....

Other features include using T<{i}> to name component types, a typle_for! macro to perform component-by-component operations, support for enums with a typle_variant!() macro, and constant-if for conditional compilation based on constant values including a typle_const! iteration variable. See the README and the test directory.

Also, see how typle is used in the hefty crate.

Macros