I have a struct Band
:
pub struct Band{
pub name: String,
pub start_dt: NaiveDateTime,
pub end_dt: NaiveDateTime,
pub stage: String,
pub selected: bool,
}
I'm using the plotters crate to plot.
I have a vector of Band
objects and want to plot rectangles. The chart for my plot has DateTime
on the y axis and Segmented values with Stage names on the x axis:
let mut chart = ChartBuilder::on(&drawing_area)
.caption(current_day, ("Arial", 30))
.set_label_area_size(LabelAreaPosition::Left, 40)
.set_label_area_size(LabelAreaPosition::Bottom, 60)
// the x axis are the sages. we want the names centered
// on an entry (i.e. it starts with half in front of a segment
// and ends half after a segment, rather than matching segments
// exactle)
// ----|---------------|-------------|-------
// main stage t stage wera stage
// for that behaviour, we need the into_segmented() command
.build_cartesian_2d(stages.into_segmented(), first_utc..last_utc)
.unwrap();
How can I get my entire vector to plot their rectangles? Whatever I do, rust complains about me using incorrect strings and thus not fulfilling trait bounds. I have wasted two hours on this and don't know how to make progress anymore.
Following are a few of the tries I had (not in the order I tried them, but whatever).
for band in bands{
let stage = band.stage.clone();
chart.draw_series(vec![
Rectangle::new(
[
(SegmentValue::Exact(&stage), band.start_dt.and_utc()),
(SegmentValue::CenterOf(&stage), band.end_dt.and_utc())
],
Into::<ShapeStyle>::into(BLACK)
)
]).unwrap();
}
|| the trait bound `for<'b> &'b plotters::element::Rectangle<(plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>: PointCollection<'b, (plotters::prelude::SegmentValue<&&str>, DateTime<Utc>)>` is not satisfied
|| |
|| 97 | chart.draw_series(vec![
|| | ^^^^^^^^^^^ the trait `for<'b> PointCollection<'b, (plotters::prelude::SegmentValue<&&str>, DateTime<Utc>)>` is not implemented for `&'b plotters::element::Rectangle<(plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>`
|| |
|| = help: the trait `PointCollection<'_, (plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>` is implemented for `&plotters::element::Rectangle<(plotters::prelude::SegmentValue<&String>, DateTime<Utc>)>`
|| = help: for that trait implementation, expected `String`, found `&str`
|| required by a bound in `ChartContext::<'a, DB, CT>::draw_series`
|| |
|| 120 | pub fn draw_series<B, E, R, S>(
|| | ----------- required by a bound in this associated function
|| ...
|| 126 | for<'b> &'b E: PointCollection<'b, CT::From, B>,
|| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ChartContext::<'a, DB, CT>::draw_series`
for band in bands{
let stage = band.stage.clone();
chart.draw_series(vec![
Rectangle::new(
[
(SegmentValue::Exact(&stage.as_str()), band.start_dt.and_utc()),
(SegmentValue::CenterOf(&band.stage.as_str()), band.end_dt.and_utc())
],
Into::<ShapeStyle>::into(BLACK)
)
]).unwrap();
}
Lifetime of stage doesn't suffice
|| `stage` does not live long enough
|| |
|| 96 | let stage = band.stage.clone();
|| | ----- binding `stage` declared here
|| 97 | chart.draw_series(vec![
|| |
||
----- borrow later used here
|| ...
|| 100 | (SegmentValue::Exact(&stage.as_str()), band.start_dt.and_utc()),
|| | ^^^^^ borrowed value does not live long enough
|| ...
|| 106 | }
|| | - `stage` dropped here while still borrowed
|| temporary value dropped while borrowed
|| |
|| 97 | chart.draw_series(vec![
|| |
----- borrow later used here
|| ...
|| 100 | (SegmentValue::Exact(&stage.as_str()), band.start_dt.and_utc()),
|| | ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|| ...
|| 105 | ]).unwrap();
|| | - temporary value is freed at the end of this statement
|| |
|| = note: consider using a `let` binding to create a longer lived value
|| `band.stage` does not live long enough
|| |
|| 95 | for band in bands{
|| |
---- binding `band` declared here
|| 96 | let stage = band.stage.clone();
|| 97 | chart.draw_series(vec![
|| |
----- borrow later used here
|| ...
|| 101 | (SegmentValue::CenterOf(&band.stage.as_str()), band.end_dt.and_utc())
|| | ^^^^^^^^^^ borrowed value does not live long enough
|| ...
|| 106 | }
|| | - `band.stage` dropped here while still borrowed
|| temporary value dropped while borrowed
|| |
|| 97 | chart.draw_series(vec![
|| | ----- borrow later used here
|| ...
|| 101 | (SegmentValue::CenterOf(&band.stage.as_str()), band.end_dt.and_utc())
|| | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|| ...
|| 105 | ]).unwrap();
|| |
- temporary value is freed at the end of this statement
|| |
|| = note: consider using a `let` binding to create a longer lived value
chart.draw_series(
bands.iter().map(|band| {
Rectangle::new(
[((SegmentValue::Exact(&band.stage.as_str())).clone(), band.start_dt.and_utc()),
((SegmentValue::CenterOf(&band.stage.as_str())).clone(), band.end_dt.and_utc())],
Into::<ShapeStyle>::into(BLACK).filled()
)
})
).unwrap();
Returns a value that still references a temporary value
|| cannot return value referencing temporary value
|| |
|| 99 | / Rectangle::new(
|| 100 | | [((SegmentValue::Exact(&band.stage.as_str())).clone(), band.start_dt.and_utc()),
|| 101
|| | | ((SegmentValue::CenterOf(&band.stage.as_str())).clone(), band.end_dt.and_utc())],
|| | |
------------------- temporary value created here
|| 102 | | Into::<ShapeStyle>::into(BLACK).filled()
|| 103 | | )
|| | |_____________^ returns a value referencing data owned by the current function
|| cannot return value referencing temporary value
|| |
|| 99 | / Rectangle::new(
|| 100 | | [((SegmentValue::Exact(&band.stage.as_str())).clone(), band.start_dt.and_utc()),
|| | |
------------------- temporary value created here
|| 101 | | ((SegmentValue::CenterOf(&band.stage.as_str())).clone(), band.end_dt.and_utc())],
|| 102 | | Into::<ShapeStyle>::into(BLACK).filled()
|| 103 | | )
|| | |_____________^ returns a value referencing data owned by the current function
The crate has a (GitHub) forum at which you get no answers, otherwise I would have asked over there...
The problem I had was mostly regarding input data. Originally, for testing I used stages.into_segmented()
where stages
was an array of &str
elements:
let stages = [
"Main Stage",
"T Stage",
"Wera Stage"
];
Thus, the into_segmented()
call created SegmentValue(&&str)
elements and I still don't know how to solve the issue for this data type.
However, once I realized this data type was problematic, I changed it to a vector of strings:
let stages: Vec<String> = vec![
String::from("Main Stage"),
String::from("T Stage"),
String::from("Wera Stage")
];
With this, getting the SegmentValue
to accept my dynamic input was rather trivial. I can now borrow the stage
String from my Band
struct and be done with it. Using a closure, it looks like this:
// draw all bands into the chart
chart.draw_series(
bands.iter().map(|band| {
Rectangle::new(
[
(SegmentValue::Exact(&band.stage), band.start_dt.and_utc()),
(SegmentValue::CenterOf(&band.stage), band.end_dt.and_utc()),
],
Into::<ShapeStyle>::into(BLACK).filled()
)
})
).unwrap();