I'm trying to write a "GPS minimap" renderer. Basically it should turn a gpx struct (from the gpx crate), and generate a png/svg for each of the waypoints, or even interpolated with a given frame rate.
For this, I want to define one trait WaypointProvider
with two implementations: SimpleWaypointProvider
and InterpolatedWayPointProvider
(to be done later). Each of these implementations should basically provide an Iterator to generate Waypoint
s which are defined like this:
pub struct Waypoint<'track> {
pub bounding_rect: Rect<f64>,
pub segment: &'track TrackSegment,
pub current_waypoint: &'track gpx::Waypoint,
}
The Waypoint's lifetime should be bound to the gpx::Track
contained inside e.g. the SimpleWaypointProvider
, which I create like this:
pub struct SimpleWaypointProvider {
track: gpx::Track,
}
impl SimpleWaypointProvider {
pub fn new(track: &gpx::Track) -> Self {
Self {
track: track.clone(),
}
}
}
(I've copied the track here to not have to bother with a lifetime in SimpleWaypointProvider
). But I don't want to copy each track for each waypoint, because these can go up to several thousands for a longer track (and even more if I do interpolation with a higher framerate).
Inside my main render method I want to receive a trait object of a WaypointProvider
so that I can dynamically create one based on CLI arguments (either SimpleWaypointProvider
or InterpolatedWayPointProvider
):
fn render(waypoint_provider: Box<dyn WaypointProvider>) {
todo!()
}
I've defined the WaypointProvider
trait as follows. It basically should be a trait which returns an ExactSizeIterator
(so that I can show a progress bar with the indicatif crate) over Waypoint
s.
My first attempt is
pub trait WaypointProvider<'track, T>: IntoIterator<Item = Waypoint<'track>, IntoIter = T>
where
T: ExactSizeIterator<Item = Waypoint<'track>>,
{
}
but I'm now having trouble implementing this. My Iterator is defined like this:
pub struct SimpleWaypointIterator<'track> {
_provider: &'track SimpleWaypointProvider,
bounding_rect: Rect<f64>,
segment: &'track gpx::TrackSegment,
// The current wp index
current_wp_index: usize,
}
Implementing the trait gives me all kind of errors, and to be honest, I'm a bit lost about the lifetimes:
impl WaypointProvider<'_, SimpleWaypointIterator<'_>> for SimpleWaypointProvider {}
impl<'provider> IntoIterator for SimpleWaypointProvider {
type Item = Waypoint<'provider>;
type IntoIter = SimpleWaypointIterator<'provider>;
fn into_iter(self) -> Self::IntoIter {
SimpleWaypointIterator::new(&self)
}
}
gives me
20 | impl<'provider> IntoIterator for SimpleWaypointProvider {
| ^^^^^^^^^ unconstrained lifetime parameter
Basically, neither the Iterator nor the waypoints should live longer than the SimpleWaypointProvider
, as that struct holds the track, which everything else references.
I guess it would be quite easy to fix, but I'm a bit lost here.
Thanks in advance