Skip to content

Instantly share code, notes, and snippets.

@krdln
Forked from Cobrand/map_2d_iter_mut.rs
Created June 30, 2016 16:53
Show Gist options
  • Save krdln/2bbd058c1b95b204e4afff4bc885f877 to your computer and use it in GitHub Desktop.
Save krdln/2bbd058c1b95b204e4afff4bc885f877 to your computer and use it in GitHub Desktop.
Trouble for creating an iterator over a 2d map : example file
#[allow(dead_code)]
// BASIC STRUCTURES
// ================
pub type Result<T> = ::std::result::Result<T,Error>;
#[derive(Debug,Copy,Clone,Eq,PartialEq)]
pub enum Reason {
NegativeMapLength,
OutOfRange,
UnknownReason
}
#[derive(Debug,Copy,Clone,Eq,PartialEq)]
pub struct Error {
pub reason: Reason
}
#[derive(Copy,Clone,Debug,PartialEq,Eq,Hash,Default)]
pub struct Position {
pub x : i32,
pub y : i32
}
// MAP IMPL
// ========
pub struct Map<T> {
contents_slice : Box<[Option<T>]>,
length: (i32,i32),
offset: (i32,i32)
}
impl<T> Map<T> {
pub fn new(length:(i32,i32),offset:(i32,i32)) -> Result<Map<T>> {
if length.0 <= 0 || length.1 <= 0 {
Err(Error{reason:Reason::NegativeMapLength})
} else {
let total_len : usize = length.0 as usize * length.1 as usize ;
let mut contents_vec : Vec<Option<T>> = Vec::with_capacity(total_len);
for _i in 0 .. total_len {
contents_vec.push(None);
};
Ok(Map::<T> {
contents_slice:contents_vec.into_boxed_slice(),
length:length,
offset:offset
})
}
}
}
fn index_to_pos(index:usize,length:(i32,i32),offset:(i32,i32)) -> Result<Position> {
debug_assert!(length.0 > 0 && length.1 > 0);
if index >= (length.0 * length.1) as usize {
Err(Error{reason:Reason::OutOfRange})
} else {
let y = index as i32 / length.0 ;
let x = index as i32 % length.0 ;
Ok(Position{x : x + offset.0,
y : y + offset.1})
}
}
// MAIN
// ====
fn main(){
println!("it compiles !");
}
// MAP ITER
// ========
use std::iter;
pub struct MapIter<'a,T:'a>{
current_index:usize,
slice:&'a [T],
length: (i32,i32),
offset: (i32,i32)
}
impl<'a,T> MapIter<'a,T>{
pub fn new(slice:&'a [T],length: (i32,i32),offset: (i32,i32)) -> MapIter<'a,T> {
MapIter {
current_index:0,
slice:slice,
length:length,
offset:offset
}
}
}
impl<'a,T:'a> iter::Iterator for MapIter<'a,T> {
type Item = (Position,&'a T) ;
fn next(&mut self) -> Option<(Position,&'a T)> {
let r = index_to_pos(self.current_index, self.length, self.offset);
match r {
Err(err) if err == Error{reason:Reason::OutOfRange} => None,
Ok(pos) => {
let current_index = self.current_index;
self.current_index += 1 ;
Some((pos,&self.slice[current_index]))
},
Err(_) => unreachable!()
}
}
}
// MAP ITER MUT
// ============
pub struct MapIterMut<'a,T:'a>{
current_index:usize,
slice:&'a mut [T],
length: (i32,i32),
offset: (i32,i32)
}
impl<'a,T> MapIterMut<'a,T>{
pub fn new(slice:&'a mut [T],length: (i32,i32),offset: (i32,i32)) -> MapIterMut<'a,T> {
MapIterMut {
current_index:0,
slice:slice,
length:length,
offset:offset
}
}
}
impl<'a,T:'a> iter::Iterator for MapIterMut<'a,T> {
type Item = (Position,&'a mut T) ;
fn next(&mut self) -> Option<(Position,&'a mut T)> {
let r = index_to_pos(self.current_index, self.length, self.offset);
match r {
Err(err) if err == Error{reason:Reason::OutOfRange} => None,
Ok(pos) => {
let slice = std::mem::replace(&mut self.slice, Default::default());
let (to_return, remaining) = slice.split_first_mut().unwrap();
self.current_index += 1;
self.slice = remaining;
Some((pos, to_return))
},
Err(_) => unreachable!()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment