winnow-rs / winnow

Making parsing a breeze
https://docs.rs/winnow
Other
525 stars 40 forks source link

Implement Accumulate for tuples (e.g. Accumulate<(T, T)> for Vec<T>) #483

Open axelkar opened 7 months ago

axelkar commented 7 months ago

Please complete the following tasks

winnow version

0.6.2

Describe your use case

Here, let me show you:

fn node(input: &mut Stream) -> Item;
/// whitespace token
fn wst(input: &mut Stream) -> Item;

let a: Vec<Item> = repeat(0.., (node, wst))
    .map(|vec: Vec<_>| vec.into_iter().map(|(a, b)| [a, b]).flatten().collect()) // make it possible without this line!!
    .parse("whatever").unwrap();

Describe the solution you'd like

#[cfg(feature = "alloc")]
impl<T> Accumulate<(T, T)> for Vec<T> {
    #[inline(always)]
    fn initial(capacity: Option<usize>) -> Self {
        match capacity {
            Some(capacity) => Vec::with_capacity(clamp_capacity::<T>(capacity)),
            None => Vec::new(),
        }
    }
    #[inline(always)]
    fn accumulate(&mut self, acc: (T, T)) {
        self.push(acc.0);
        self.push(acc.1);
    }
}
// the same for (T, T, T), (T, T, T, T) and so on until what? 12 items?

Alternatives, if applicable

maybe you could instead use impl Into<[T; N]>: https://doc.rust-lang.org/std/primitive.tuple.html#impl-From%3C(T,)%3E-for-%5BT;+1%5D

Additional Context

No response

axelkar commented 7 months ago

Oh and Option in any of the tuple's fields would be great too. Just noticed that I only optionally need the whitespace token.

epage commented 7 months ago

I worry about the number of combinations we'd be dealing with and how that would affect users in different ways (reading docs, compile times, etc).

Is there a reason to not use repeat().fold() instead?

axelkar commented 7 months ago

I didn't even think of making a Vec in fold. Thanks! After that this issue doesn't concern me nearly as much, but it's still manual.