Make a function accept two things that are similar

Given a LineSegment and fn contour1 and fn contour2.
How do I make a fn contour that takes both &[LineSegment] and &[(Vec3, Vec3)] ?

struct Vec3 {
    x: f32,
    y: f32,
    z: f32,
}
struct LineSegment(Vec3, Vec3);

// take a slice of LineSegment
fn contour1(lines: &[LineSegment]) {
    for LineSegment(a, b) in lines {
        do_something(*a, *b);
    }
}

// take a slice of (Vec3, Vec3)
fn contour2(lines: &[(Vec3, Vec3)]) {
    for (a, b) in lines {
        do_something(*a, *b);
    }
}

fn contour<T: ?>(lines: T) {
    for (a, b) in lines {
        do_something(*a, *b);
    }
}

I'd probably do this, but you could make a dedicated trait if you wanted.

#[derive(Clone, Copy)]
struct LineSegment(Vec3, Vec3);

impl From<(Vec3, Vec3)> for LineSegment {
    fn from((a, b): (Vec3, Vec3)) -> Self {
        Self(a, b)
    }
}

impl<'a> From<&'a (Vec3, Vec3)> for LineSegment {
    fn from(value: &'a (Vec3, Vec3)) -> Self {
        Self::from(*value)
    }
}

impl<'a> From<&'a LineSegment> for LineSegment {
    fn from(value: &'a LineSegment) -> Self {
        *value
    }
}

fn contour<T>(lines: T)
where
    T: IntoIterator<Item: Into<LineSegment>>,
{
    for LineSegment(a, b) in lines.into_iter().map(|line| line.into()) {
        do_something(a, b);
    }
}
2 Likes