I’m new to Rust and I’m still struggling with the borrowing concept in combination with the TryFrom function from the geo_types
crate.
I basically want to do different things depending on the actual Geometry
type:
use geo_types::{Geometry, Point, LineString};
fn some_func(g : Geometry<f64>) {
if let Ok(p) = Point::try_from(g) {
print!("POINT");
} else if let Ok(ls) = LineString::try_from(g) {
print!("LINESTRING");
} else {
print!("UNKNOWN");
}
}
but this fails with:
error[E0382]: use of moved value: `g`
--> src/main.rs:7:49
|
4 | fn some_func(g : Geometry<f64>) {
| - move occurs because `g` has type `Geometry`, which does not implement the `Copy` trait
5 | if let Ok(p) = Point::try_from(g) {
| - value moved here
6 | print!("POINT");
7 | } else if let Ok(ls) = LineString::try_from(g) {
| ^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
5 | if let Ok(p) = Point::try_from(g.clone()) {
| ++++++++
So I was changing the function to take a geometry refernce:
fn some_func(g : &Geometry<f64>)
but that fails with:
the trait
From<&Geometry>
is not implemented forgeo_types::Point<_>
Next thing I tried is to de-reference the geometry:
Point::try_from(*g)
but this also fails with:
cannot move out of
*g
which is behind a shared reference
move occurs because*g
has typeGeometry
, which does not implement theCopy
trait
So what can I do to get this code working or how can I do this differently?
>Solution :
Note that Geometry is an enum, so you should use pattern matching to check which variant you are using.
pub enum Geometry<T: CoordNum = f64> {
Point(Point<T>),
Line(Line<T>),
LineString(LineString<T>),
Polygon(Polygon<T>),
MultiPoint(MultiPoint<T>),
MultiLineString(MultiLineString<T>),
MultiPolygon(MultiPolygon<T>),
GeometryCollection(GeometryCollection<T>),
Rect(Rect<T>),
Triangle(Triangle<T>),
}
So you can rewrite your function as follows:
use geo_types::{Geometry, Point, LineString};
fn some_func(g : Geometry<f64>) {
match g {
Geometry::Point(_) => print!("POINT"),
Geometry::LineString(_) => print!("LINESTRING"),
// It's not really unknown, because there are other enum variants,
// but I left it to not change your original (intended?) bahavior.
_ -> print!("UNKNOWN")
}
}