picto/iter/
coordinates.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15use crate::region::Region;
16
17/// Iterator over X and Y coordinates within an `Region`.
18#[derive(Eq, PartialEq, Debug)]
19pub struct Coordinates {
20	x: u32,
21	y: u32,
22
23	region: Region,
24}
25
26impl Coordinates {
27	/// Create a new `Iterator` for the given `Region`.
28	#[inline]
29	pub fn new(region: Region) -> Self {
30		Coordinates { x: 0, y: 0, region }
31	}
32
33	/// The `Region` being iterated over.
34	#[inline]
35	pub fn region(&self) -> Region {
36		self.region
37	}
38}
39
40impl Iterator for Coordinates {
41	type Item = (u32, u32);
42
43	#[inline]
44	fn next(&mut self) -> Option<Self::Item> {
45		if self.x >= self.region.width {
46			self.x = 0;
47			self.y += 1;
48		}
49
50		if self.y >= self.region.height {
51			return None;
52		}
53
54		self.x += 1;
55
56		Some((self.x - 1 + self.region.x, self.y + self.region.y))
57	}
58
59	#[inline]
60	fn size_hint(&self) -> (usize, Option<usize>) {
61		(self.len(), Some(self.len()))
62	}
63}
64
65impl ExactSizeIterator for Coordinates {
66	#[inline]
67	fn len(&self) -> usize {
68		let length = self.region.width * self.region.height;
69		let remaining = length - (self.y * self.region.width + self.x);
70
71		remaining as usize
72	}
73}
74
75#[cfg(test)]
76mod test {
77	use super::*;
78	use crate::region::Region;
79
80	#[test]
81	fn size_hint() {
82		let mut coord = Coordinates::new(Region::from(0, 0, 2, 2));
83
84		assert_eq!(4, coord.size_hint().0);
85		coord.next().unwrap();
86		assert_eq!(3, coord.size_hint().0);
87		coord.next().unwrap();
88		assert_eq!(2, coord.size_hint().0);
89		coord.next().unwrap();
90		assert_eq!(1, coord.size_hint().0);
91		coord.next().unwrap();
92		assert_eq!(0, coord.size_hint().0);
93	}
94}