Crate tupley

Crate tupley 

Source
Expand description

§tupley

§Intro

Extension for primitive tuple (Hlist based on recursive structure).
You could use it to contain elements with different types.

§Struct

Basic structure:

// NonEmpty Tuple
struct Tuple<First, Tail>(First, Tail);
// Empty Tuple used as last element
struct Unit;

trait TupleY {
    const LEN: usize;
    // ......
    // ......
}

impl TupleY for Unit {
    const LEN: usize = 0;
    // ......
    // ......
}
impl<First, Tail: TupleY> TupleY for Tuple<First, Tail> {
    const LEN: usize = <Tail as TupleY>::LEN + 1;
    // ......
    // ......
}
use tupley::prelude::*;

let t = tup!(1, 2.0, false);
// Tuple(1, Tuple(2.0, Tuple(false, Unit)))

§Usage

  • generate new Tuple:
use tupley::prelude::*;

fn tuple_new() {
    let t = tup!();
    assert_eq!(t, Unit);

    let t = tup!(1);
    assert_eq!(t, Tuple(1, Unit));

    let t = tup!(1, 2.0, "3");
    assert_eq!(t, Tuple(1, Tuple(2.0, Tuple("3", Unit))));
}
  • check empty:
use tupley::prelude::*;

fn tuple_is_empty() {
    let t = tup!();
    assert!(t.is_empty());

    let t = tup!(1, false);
    assert!(!t.is_empty());
}
  • generate new Tuple type:
use tupley::prelude::*;

fn tuple_type() {
    let t = <tup_t!(i32, &str, bool)>::default();
    assert_eq!(t, tup!(0, "", false));

    let t: tup_t!(i32, &str, bool) = Default::default();
    assert_eq!(t, tup!(0, "", false));

    #[derive(Default, Debug, PartialEq, Eq)]
    struct Wrapper<'a> {
        a: tup_t!(i32, i32),
        b: tup_t!(&'a str, bool),
    }
    let t = Wrapper::default();
    assert_eq!(t, Wrapper{
        a: tup!(0, 0),
        b: tup!("", false),
    })
}
  • generate Tuple pattern for macthing:
use tupley::prelude::*;

fn tuple_pattern() {
    let t = tup!();
    let tup_pat!() = t;

    let t = tup!(1);
    let tup_pat!(a) = t;
    assert_eq!(a, tup!(1));

    let t = tup!("", 2, 3.0);
    let tup_pat!(a, b, c) = t;
    assert_eq!(a, "");
    assert_eq!(b, 2);
    assert_eq!(c, tup!(3.0));

    // don't match anything
    let t = tup!(1, 2, 3, 4, 5);
    let tup_pat!(..) = t;

    let t = tup!(1, 2.0, "", vec![1], true);
    let tup_pat!(a, b, c) = t;
    assert_eq!(a, 1);
    assert_eq!(b, 2.0);
    assert_eq!(c, tup!("", vec![1], true)); // match the rest all
}
  • get length of every tuple:
use tupley::prelude::*;

fn tuple_len() {
    let t = tup!();
    assert_eq!(0, t.len());

    let t = tup!(1, false);
    assert_eq!(2, t.len());

    let t = tup!(1, 2, 3);
    assert_eq!(3, t.len());
}
  • add/combine two tuples into one (or pushing back/front new element)
use tupley::prelude::*;

fn tuple_add() {
    let t1 = tup!(1, 2);
    let t2 = tup!(3.0, false, Some(1));
    let t = t1 + t2;
    assert_eq!(t, tup!(1, 2, 3.0, false, Some(1)));
}

fn tuple_push() {
    let t = tup!();
    let t = t.push_back(1);
    let t = t.push_back("str");
    let t = t.push_back(false);
    assert_eq!(t, tup!(1, "str", false));

    let t = tup!();
    let t = t.push_front(1);
    let t = t.push_front("str");
    let t = t.push_front(false);
    assert_eq!(t, tup!(false, "str", 1));
}
  • functor map as_ref/as_mut/to_some/to_ok:
use tupley::prelude::*;

fn tuple_as_to() {
    let t = tup!(1, "str", 3.0, false);
    assert_eq!(t.as_ref(), tup!(&1, &"str", &3.0, &false));

    let mut t = tup!(1, "str", 3.0, false);
    assert_eq!(t.as_mut(), tup!(&mut 1, &mut "str", &mut 3.0, &mut false));

    let t = tup!(1, "str", 3.0, false);
    assert_eq!(t.to_some(), tup!(Some(1), Some("str"), Some(3.0), Some(false)));

    let t = tup!(1, "str", 3.0, false);
    assert_eq!(t.to_ok::<()>(), tup!(Ok(1), Ok("str"), Ok(3.0), Ok(false)));
}
  • check length in compile-time for tuples passed in (using const generics):

Notice: You should enable feature len-generic switch toolchain into nightly

#![cfg_attr(feature = "len-generic", feature(generic_const_exprs))]
use tupley::prelude::*;

#[cfg(feature = "len-generic")]
fn tuple_len_generic() {
    let t = tup!(1, 2, 3);

    fn eq_yes<T: TupleLenEq<3>>(_: T) {}
    eq_yes(t);

    fn gt_yes<T: TupleLenGt<2>>(_: T) {}
    gt_yes(t);

    fn ge_yes_1<T: TupleLenGe<3>>(_: T) {}
    ge_yes_1(t);

    fn ge_yes_2<T: TupleLenGe<2>>(_: T) {}
    ge_yes_2(t);

    // LEN >= 3, LEN < 4
    fn range_yes<T: TupleLenRange<3, 4>>(_: T) {}
    range_yes(t);

    // The following will failed in compile time
    //
    //
    // fn ge_err<T: TupleLenGe<4>>(_: T) {}
    // ge_err(t);
    //
    //
    // fn gt_err<T: TupleLenGt<4>>(_: T) {}
    // gt_err(t);
    //
    //
    // fn eq_err<T: TupleLenEq<2>>(_: T) {}
    // eq_err(t);
}

More work WIP.

Modules§

macros
Some useful macros
prelude
tuple

Macros§

tup
generate new Tuple:
tup_pat
generate Tuple pattern for macthing:
tup_t
generate new Tuple type: