1

I want to migrate some code from C to Rust for learning purposes and to make my learning library a bit more multi-lingual.

The problem is that I know there's a way to integrate C libraries into Rust. That way I could use calloc in Rust to allow creating my array with a range specified at runtime.

But I don't want to use calloc here - I'd like to see the Rust way. But I really don't want to use vec! either; I had some stupid issues with it before so I don't want to use it just yet.

Here is the code:

pub struct Canvas {
    width: usize,
    height: usize,
    array: [char], // I want to declare its type but not its size yet
}

impl Canvas{
    pub fn new (&self, width: usize, height: usize) -> Canvas {
        Canvas {
            width: width,
            height: height,
            array: calloc(width, height), // alternative to calloc ?            }
    }
}

I hope my question is still idiomatic to the Rust way of code.

2 Answers 2

5

i want to access that array with coordinates style

Something like this?

pub struct Canvas {
    width: usize,
    height: usize,
    data: Vec<u8>,
}

impl Canvas {
    pub fn new(width: usize, height: usize) -> Canvas {
        Canvas {
            width: width,
            height: height,
            data: vec![0; width*height],
        }
    }

    fn coords_to_index(&self, x: usize, y: usize) -> Result<usize, &'static str> {
        if x<self.width && y<self.height {
            Ok(x+y*self.width)
        } else {
            Err("Coordinates are out of bounds")
        }
    }

    pub fn get(&self, x: usize, y: usize) -> Result<u8, &'static str> {
        self.coords_to_index(x, y).map(|index| self.data[index])
    }

    pub fn set(&mut self, x: usize, y: usize, new_value: u8) -> Result<(), &'static str>{
        self.coords_to_index(x, y).map(|index| {self.data[index]=new_value;})
    }
}

fn main() {
    let mut canvas = Canvas::new(100, 100);
    println!("{:?}", canvas.get(50, 50)); // Ok(0)
    println!("{:?}", canvas.get(101, 50)); // Err("Coordinates are out of bounds")
    println!("{:?}", canvas.set(50, 50, 128)); // Ok(())
    println!("{:?}", canvas.set(101, 50, 128)); // Err("Coordinates are out of bounds")
    println!("{:?}", canvas.get(50, 50)); // Ok(128)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Exactly what I was looking for !!
For a "built-in" feel, note the presence of the Index and IndexMut which could implement for (usize, usize). They cannot report errors, so they would come in supplement to the methods you wrote here, and then you could use canvas[(50,50)] = 128.
5

First of all, I deeply suspect you don't want char; I'm assuming you want an "array of bytes", in which case you want u8.

Secondly, you can't really use [u8] like this. I'm not going to get into the why because that would just derail the answer. For now: if you see a [T] that isn't behind a reference or pointer of some kind, it's probably a mistake.

Finally, this is what Vec is for; use it. You say you don't want to use it, but don't specify why. Vec is how you allocate a dynamically sized array in Rust. If you're trying to allocate a structure that's compatible with the exact same structure in C, then the question changes quite a bit, and you should make that clear.

Assuming what you wanted was the "Rust equivalent" of doing it in C:

pub struct Canvas {
    width: usize,
    height: usize,
    array: Vec<u8>,
}

impl Canvas {
    pub fn new(width: usize, height: usize) -> Canvas {
        Canvas {
            width: width,
            height: height,
            array: vec![0; width*height],
        }
    }
}

3 Comments

OK then I'll use vec! macro. But I don't come along with them very well. When I construct my canvas with a width of 10 and height of 10 the "array" binding will hold a vec with a length of 100 (index range 0-99). After using this API I want to access the 99th index of the array which I could to with array[99] - no problem so far. But when i want to access that array with coordinates style for a mutli-dimensional array I had to do array[9][9] which is not possible and array[9*9] will result in array[81] and not 9 in width and 9 in height...thats the issue I have here tbh
@xetra11 viewing a flat array as a 2d array can be done with trivial arithmetics (x + y*width, for example, in row-major order (that's how it is called I think)).
fix pub fn new(&self, width: usize, height: usize) to pub fn new(width: usize, height: usize)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.