3
\$\begingroup\$

This is the first time I‘ve used Rust, and I'd like to have some feedback on this project. The Grid class should be able to store objects of any type; it's a simple 2D grid that implements the bare minimum of interfaces. Only the copy_sub_grid function is a bit fancy here, nothing else is too crazy.

pub type Coordinate = (usize, usize);
pub type Dimension = (usize, usize);

pub type GridAction<T> = fn(target: &mut T);

pub struct Grid<T> {
    column_count: usize,
    row_count: usize,
    data: Vec<T>
}

impl<T> Grid<T>
where
    T: Copy,
{
    pub fn new(column_count: usize, row_count: usize, default: T) -> Self
    {
        let capacity = row_count * column_count;

        Self {
            column_count: column_count,
            row_count: row_count,
            data: vec![default; capacity],
        }
    }

    pub fn get_capacity(&self) -> usize {
        return self.row_count * self.column_count;
    }

    pub fn height(&self) -> usize {
        return self.row_count;
    }

    pub fn width(&self) -> usize {
        return self.column_count;
    }

    pub fn get_mut(&mut self, position: Coordinate) -> Option<&mut T> {
        if self.in_grid(position) {
            let i = self.get_index(position);
            return Some(&mut self.data[i]);
        } else {
            return None
        }
    }

    pub fn get(&self, position: Coordinate) -> Option<&T> {
        if self.in_grid(position) {
            return Some(&self.data[self.get_index(position)]);
        } else {
            None
        }
    }

    pub fn set(&mut self, position: Coordinate, new_value: T) {
        match self.get_mut(position) {
            Some(value) => {
                *value = new_value;
            }
            None => ()
        }
    }

    pub fn map(&mut self, func: GridAction<T>) {
        for element in &mut self.data {
            func(element);
        }
    }

    pub fn swap(&mut self, position1: Coordinate, position2: Coordinate) {
        let index1 = self.get_index(position1);
        let index2 = self.get_index(position2);
        self.data.swap(index1, index2);
    }

    pub fn copy_sub_grid(&self, (x, y): Coordinate, (w, h): Dimension, default: T) -> Option<Grid<T>> {
        if self.in_grid((x + w, y + h)) {
            let mut new_grid = Grid::new(w, h, default);

            for row_i in y .. y + h {
                for col_i in x .. x + w {
                    let flat_i = self.get_index((col_i, row_i));
                    let value = self.data[flat_i];
                    new_grid.set((col_i - x, row_i - y), value);
                }
            }

            return Some(new_grid);
        } else {
            return None;
        }
    }

    fn get_index(&self, (x, y): Coordinate) -> usize {
        return x + y * self.column_count;
    }

    fn in_grid(&self, (x, y): Coordinate) -> bool {
        return x < self.column_count && y < self.row_count;
    }
}

#[test]
fn test_new() {
    let mut _grid = Grid::new(10, 15, 0);
    assert_eq!(150, _grid.get_capacity());
    assert_eq!(15, _grid.height());
    assert_eq!(10, _grid.width());
}

#[test]
fn test_get_set() {
    let mut _grid = Grid::new(10, 15, 0);
    _grid.set((5, 5), 10);

    let _value = _grid.get_mut((5,5)).unwrap();
    assert_eq!(&10, _value);
    *_value = 11;
    assert_eq!(&11, _value);
    assert_eq!(&11, _grid.get((5,5)).unwrap());
}

#[test]
fn test_swap() {
    let mut _grid = Grid::new(10, 15, 0);
    _grid.set((5, 5), 10);
    _grid.swap((5,5), (1,2));

    assert_eq!(&0, _grid.get((5,5)).unwrap());
    assert_eq!(&10, _grid.get((1,2)).unwrap());
}

#[test]
fn test_map() {
    let mut _grid = Grid::new(10, 15, 1);
    _grid.map(|x| *x = *x * 2);
    assert_eq!(&2, _grid.get((5,5)).unwrap());
}

#[test]
fn test_sub_grid() {
    let mut _grid = Grid::new(10, 15, 1);
    _grid.set((5, 5), 10);
    let new_grid = _grid.copy_sub_grid((2,2), (6, 6), 1).unwrap();
    assert_eq!(36, new_grid.get_capacity());
    assert_eq!(6, new_grid.height());
    assert_eq!(6, new_grid.width());
    assert_eq!(&10, new_grid.get((3,3)).unwrap());
}
\$\endgroup\$
  • 2
    \$\begingroup\$ This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. Questions should include a description of what the code does \$\endgroup\$ – Ethan Bierlein Nov 19 '19 at 20:42
  • \$\begingroup\$ @EthanBierlein What context is missing? It's a 2D grid, with basic grid functions, there even are unit tests at the bottom to explain what the code does. I really don't believe this is incomplete. \$\endgroup\$ – IEatBagels Nov 21 '19 at 13:39
  • 1
    \$\begingroup\$ I think some description was missing in the initial message. I edited it so that readers can grasp what the code does without reading it. \$\endgroup\$ – Stud Nov 21 '19 at 17:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.