quittle
quittle

Reputation: 906

How do I create a macro that transforms inputs into a tuple?

I want to avoid creating many numbered functions and duplicated code if possible. I'm writing a program that is parsing a config file containing lines like the following and I want to simplify my logic for parsing it with some helper functions.

I would like advice on the idiomatic Rust way of approaching this to avoid code duplication while keeping it readable. My best guess is if I could use a macro that could somehow convert the input into a block that results in a tuple but don't know how to write that while including the iteration and transformation steps.

Example Input

attribute-name
1 2
other-attribute
3 4 5

Current parsing implementation

/// Splits `s` into two values, using `pattern` to find the split. If not enough values
/// are present, `missing_err` is returned.
/// It then `transform`s each entry, returning the result as a tuple
fn split_str_into_2<'a, T, E>(
    s: &'a str,
    pattern: &str,
    transform: &dyn Fn(&str) -> T,
    missing_err: &E,
) -> Result<(T, T), E> where E: Copy {
    let mut split = s.splitn(2, pattern);
    Ok((
        transform(split.next().ok_or_else(|| *missing_err)?),
        transform(split.next().ok_or_else(|| *missing_err)?),
    ))
}

/// Same as above but parses into a tuple of 3
fn split_str_into_3<'a, T, E>( ...

Calling Code

let (width, height) = split_str_into_2(
    input_line, " ", |entry| i32::from_str_radix(entry, 10), &MyError::new("Missing number entry"))?;

Upvotes: 0

Views: 491

Answers (1)

phimuemue
phimuemue

Reputation: 35983

I do not know your exact use, but one possibility if you want to collect an iterator into a tuple would be Itertools::collect_tuple.

This, for now is implemented for tuples up to length 4. If you need more elements, you could try adapting the approach taken in itertools or filing an issue/PR on the project.

Upvotes: 1

Related Questions