@@ -132,6 +132,37 @@ impl<T> Grid<T> {
132132 }
133133 }
134134
135+ pub fn cardinal_neighbours ( & self , location : Location ) -> Option < [ & T ; 8 ] >
136+ where
137+ T : Default + Copy ,
138+ {
139+ // Check boundaries, we don't support fetching the neighbours at the edge
140+ if location. x ( ) <= 0
141+ || location. x ( ) >= self . width ( )
142+ || location. y ( ) <= 0
143+ || location. y ( ) >= self . height ( )
144+ {
145+ return None ;
146+ }
147+
148+ let ix = ( location. x ( ) + location. y ( ) * self . width ( ) ) as usize ;
149+ let y_step = self . width ( ) as usize ;
150+
151+ // We've checked the bounds
152+ unsafe {
153+ Some ( [
154+ self . items . get_unchecked ( ix - y_step) ,
155+ self . items . get_unchecked ( ix - y_step + 1 ) ,
156+ self . items . get_unchecked ( ix + 1 ) ,
157+ self . items . get_unchecked ( ix + y_step + 1 ) ,
158+ self . items . get_unchecked ( ix + y_step) ,
159+ self . items . get_unchecked ( ix + y_step - 1 ) ,
160+ self . items . get_unchecked ( ix - 1 ) ,
161+ self . items . get_unchecked ( ix - y_step - 1 ) ,
162+ ] )
163+ }
164+ }
165+
135166 pub fn get ( & self , location : Location ) -> Option < & T > {
136167 let ix = self . index_from_location ( location) ?;
137168 self . items . get ( ix)
@@ -172,17 +203,12 @@ impl<T> Grid<T> {
172203 }
173204
174205 pub fn entries ( & self ) -> impl Iterator < Item = ( Location , & T ) > {
175- self . items
176- . iter ( )
177- . enumerate ( )
178- . map ( |( index, value) | ( ( self . size , index) . into ( ) , value) )
206+ Indexed :: new ( self . items . iter ( ) , self . width ( ) )
179207 }
180208
181209 pub fn entries_mut ( & mut self ) -> impl Iterator < Item = ( Location , & mut T ) > {
182- self . items
183- . iter_mut ( )
184- . enumerate ( )
185- . map ( |( index, value) | ( ( self . size , index) . into ( ) , value) )
210+ let width = self . width ( ) ;
211+ Indexed :: new ( self . items . iter_mut ( ) , width)
186212 }
187213
188214 pub fn values ( & self ) -> impl Iterator < Item = & T > { self . items . iter ( ) }
@@ -658,3 +684,37 @@ mod tests {
658684 ) ;
659685 }
660686}
687+
688+ #[ derive( Clone , Debug ) ]
689+ pub struct Indexed < I > {
690+ iter : I ,
691+ x : i32 ,
692+ y : i32 ,
693+ width : i32 ,
694+ }
695+
696+ impl < I > Indexed < I > {
697+ fn new ( iter : I , width : i32 ) -> Indexed < I > { Indexed { iter, x : 0 , y : 0 , width } }
698+ }
699+
700+ impl < I > Iterator for Indexed < I >
701+ where
702+ I : Iterator ,
703+ {
704+ type Item = ( Location , <I as Iterator >:: Item ) ;
705+
706+ #[ inline]
707+ fn next ( & mut self ) -> Option < Self :: Item > {
708+ let item = self . iter . next ( ) ?;
709+ let location = point2 ( self . x , self . y ) ;
710+ self . x += 1 ;
711+ if self . x >= self . width {
712+ self . x = 0 ;
713+ self . y += 1 ;
714+ }
715+ Some ( ( location, item) )
716+ }
717+
718+ #[ inline]
719+ fn size_hint ( & self ) -> ( usize , Option < usize > ) { self . iter . size_hint ( ) }
720+ }
0 commit comments