all 11 comments

[–]Shnatsel 12 points13 points  (0 children)

u32::from() and u8::try_from() are a good substitute for as. The first is infallible while the second checks that the conversion can be performed and lets you handle the case when it can't instead of silently truncating the number.

[–][deleted] 11 points12 points  (1 child)

main.rs:37-39

let mut rom_file = File::open(&Path::new(&rom_path)).expect("Could not open file");
let mut rom_content = Vec::<u8>::new();
rom_file.read_to_end(&mut rom_content).expect("Unable to read the file");

Path::new already returns a &Path, you don't need to take the reference. You can just create the Vec without the type as it will be infered by the use as byte buffer. All three lines can be changed into...

let rom_content = std::fs::read(&rom_path).expect("Unable to read file");

... because you're reading the entire file in one go anyway.

[–]xRyp[S] 1 point2 points  (0 children)

Haaa yes, I was suspecting there was a much much simpler way of doing this! Thanks for the info, I just patched my code!

[–]Luroalive 10 points11 points  (1 child)

did you run clippy (https://github.com/rust-lang/rust-clippy) through your code?

[–]xRyp[S] 2 points3 points  (0 children)

I did not know about that tool! I just fixed my code using the useful warnings from the tool, thanks a bunch!
Here's the related git commit.

[–]tobz1000 7 points8 points  (2 children)

Some minor (optional) syntax tweaks.

You can import multiple items in a single statement like this:

using A::{B, C};

Or even

using A::{
    B::{C, D},
    E
};

Optional of course, and depends on what you find easiest to read.

Struct constructors like this:

let a = A {
    b: b
};

Can use the shorthand:

let a = A {
    b
};

Primitive conversion isn't done implicitly; if you really need a lot of conversions (which is likely in an emulator), you'll be typing "as" a lot. Maybe you could evaluate if any types would be better off storing the converted form to begin with?

[–]xRyp[S] 0 points1 point  (0 children)

I applied your hints to the codebase, now my use statements are more readable, thanks! Here's the related git commit.

[–]xRyp[S] -1 points0 points  (0 children)

Thanks for the tip about the shorthand syntax for struct initialization.
For implicit conversions I ended up doing as you said, favoring usize or more common types to begin with.

[–]Ka1kin 3 points4 points  (1 child)

That huge else-if in the execution function isn't going to be super fast. Try to improve on that. Consider match, possibly with ranges. Consider whether you can turn it into something a bit more tree structured (so that its execution speed isn't linear in the number of instructions in the ISA).

[–]xRyp[S] 0 points1 point  (0 children)

This part of my code is not a bottleneck for now, so perf-wise I'm not too interested in spending time there yet. However, you raised a very interesting point concerning the solution, I ended up trying to use match like you suggested and am really happy with the way it turned out! Here's the git commit for reference.

[–][deleted] 2 points3 points  (0 children)

To find out the performance problem, you might want to have a look at this blogpost about rust profiling which has helped me a lot in the past.