actually there is a way to preserve mutable polygon iterator
authoralfadur
Mon, 05 Nov 2018 21:21:53 +0300
changeset 14139 09f62bb046ef
parent 14138 a65b60f36b96
child 14140 7f5a591e1c43
actually there is a way to preserve mutable polygon iterator
rust/integral-geometry/src/lib.rs
rust/landgen/src/outline.rs
--- a/rust/integral-geometry/src/lib.rs	Mon Nov 05 20:22:09 2018 +0300
+++ b/rust/integral-geometry/src/lib.rs	Mon Nov 05 21:21:53 2018 +0300
@@ -1,8 +1,11 @@
 extern crate fpnum;
 
 use fpnum::distance;
-use std::cmp::max;
-use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign};
+use std::{
+    cmp::max,
+    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign}
+};
+
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub struct Point {
@@ -464,18 +467,16 @@
         (&self.vertices[..self.edges_count()]).iter()
     }
 
-    fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut Point> + 'a {
+    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut Point> + 'a {
         let edges_count = self.edges_count();
-        (&mut self.vertices[..edges_count]).iter_mut()
+        let start = self.vertices.as_mut_ptr();
+        let end = unsafe { start.add(self.vertices.len()) };
+        PolygonPointsIteratorMut { source: self, start, end }
     }
 
-    pub fn for_each<F>(&mut self, f: F)
-        where F: (Fn(&mut Point))
-    {
+    fn force_close(&mut self) {
         if !self.vertices.is_empty() {
-            self.iter_mut().for_each(f);
-            let edges_count = self.edges_count();
-            self.vertices[edges_count] = self.vertices[0]
+            self.vertices[0] = self.vertices[self.vertices.len() - 1];
         }
     }
 
@@ -487,6 +488,34 @@
     }
 }
 
+struct PolygonPointsIteratorMut<'a> {
+    source: &'a mut Polygon,
+    start: *mut Point,
+    end: *mut Point
+}
+
+impl <'a> Iterator for PolygonPointsIteratorMut<'a> {
+    type Item = &'a mut Point;
+
+    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
+        if self.start == self.end {
+            None
+        } else {
+            unsafe {
+                let result = &mut *self.start;
+                self.start = self.start.add(1);
+                Some(result)
+            }
+        }
+    }
+}
+
+impl <'a> Drop for PolygonPointsIteratorMut<'a> {
+    fn drop(&mut self) {
+        self.source.force_close();
+    }
+}
+
 impl From<Vec<Point>> for Polygon {
     fn from(mut v: Vec<Point>) -> Self {
         if !v.is_empty() && v[0] != v[v.len() - 1] {
--- a/rust/landgen/src/outline.rs	Mon Nov 05 20:22:09 2018 +0300
+++ b/rust/landgen/src/outline.rs	Mon Nov 05 21:21:53 2018 +0300
@@ -54,11 +54,11 @@
             .chain(self.fill_points.iter())
     }
 
-    pub fn for_each<F>(&mut self, f: F)
-        where F: (Fn(&mut Point))
-    {
-        self.islands.iter_mut().for_each(|p| p.for_each(|x| f(x)));
-        self.fill_points.iter_mut().for_each(|p| f(p));
+    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Point> {
+        self.islands
+            .iter_mut()
+            .flat_map(|i| i.iter_mut())
+            .chain(self.fill_points.iter_mut())
     }
 
     fn divide_edge<I: Iterator<Item = u32>>(
@@ -289,12 +289,14 @@
 
     pub fn mirror(&mut self) {
         let r = self.size.width as i32 - 1;
-        self.for_each(|p| p.x = r - p.x);
+
+        self.iter_mut().for_each(|p| p.x = r - p.x);
     }
 
     pub fn flip(&mut self) {
         let t = self.size.height as i32 - 1;
-        self.for_each(|p| p.y = t - p.y);
+
+        self.iter_mut().for_each(|p| p.y = t - p.y);
     }
 }
 
@@ -321,7 +323,7 @@
         Some(&Line::new(Point::new(20, 15), Point::new(10, 15)))
     );
 
-    points.for_each(|p| p.x = 2);
+    points.iter_mut().for_each(|p| p.x = 2);
 
     assert_eq!(points.fill_points[0].x, 2);
     assert_eq!(points.islands[0].get_edge(0).start.x, 2);