# HG changeset patch # User alfadur # Date 1541442113 -10800 # Node ID 09f62bb046efb5cf8b2e9cec89b255c00729b14e # Parent a65b60f36b96da9a968126937d64996ec29a7932 actually there is a way to preserve mutable polygon iterator diff -r a65b60f36b96 -r 09f62bb046ef rust/integral-geometry/src/lib.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 + 'a { + pub fn iter_mut<'a>(&'a mut self) -> impl Iterator + '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(&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<::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> for Polygon { fn from(mut v: Vec) -> Self { if !v.is_empty() && v[0] != v[v.len() - 1] { diff -r a65b60f36b96 -r 09f62bb046ef rust/landgen/src/outline.rs --- 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(&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 { + self.islands + .iter_mut() + .flat_map(|i| i.iter_mut()) + .chain(self.fill_points.iter_mut()) } fn divide_edge>( @@ -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);