I am defining a map structure:
struct Point { x: isize, y: isize };
enum MapItem { Pipe, Ground, Start };
struct Map {
map: Vec<Vec<MapItem>>>,
start: Option<Point>,
}
I have implemented Index and IndexMut on the Map to support Map[Point] operations.
However, the map has constraints around the Start map item:
- Only one
Startmap item may be defined in the map. - When a map item is changed from anything else to
Start, themap.startfield is set toSome(location). - When a map item is changed from
Startto anything else, themap.startfield is set toNone.
I don't know how to maintain these constraints while implementing IndexMut. Is there any way to add a validity constraint to the &mut MapItem returned by IndexMut, or do I have to remove the IndexMut implementation and just add a set(location, item) method to the base implementation of Map?
By jumping through a lot of interior-mutability-hoops, you can do that. That'd require a lot of code, just to be able to write
mymap[mypoint] = ...instead ofmymap.set_point(...)- most likely not worth the trouble.The problem is that
std::ops::IndexMutshares it'sOutput-type withstd::ops::Index, andstd::ops::IndexMut::index_mut()is defined to return a&mut Self::Output. Since you have to return a mutable reference fromIndexMut, you can't actually return some proxy-object that does the enforcement after the fact - there is no way to observe what happened after you gave out that&mut-reference.