0dmg

Learning Rust by building a partial Game Boy emulator.

This project is maintained by jeremyBanks

Trait-based function overloading in Rust

Figured this out so that I can have an LD(dest, source) wrapper function that works for different registers, for zerodmg_codes::Instructions. We probably won’t use it in the zerodmg_emulator::CPU at this point, but I’m planning to use it to generate a demo ROM, so I’d like a nice syntax.

See this in the Rust Playground or below:

#![allow(non_snake_case)]

fn main() {
    use OneByteRegister::*;
    use TwoByteRegister::*;

    LD(A, 0b_0000_1111_u8);
    LD(F, A);
    LD(HL, 0b_0000_1111_0000_1111_u16);
    LD(DC, HL);
}

#[derive(Debug)]
enum OneByteRegister {
    A,
    F,
}

#[derive(Debug)]
enum TwoByteRegister {
    HL,
    DC,
}

fn LD<A : Load<B>, B>(a: A, b: B) {
    Load::LD(a, b)
}

trait Load<Source> {
    fn LD(self, source: Source);
}

impl Load<u8> for OneByteRegister {
    fn LD(self, value: u8) {
        println!("LD_u8_immediate {:?} <- {:?}", self, value);
    }
}

impl Load<u16> for TwoByteRegister {
    fn LD(self, value: u16) {
        println!("LD_u16_immediate {:?} <- {:?}", self, value);
    }
}

impl Load<OneByteRegister> for OneByteRegister {
    fn LD(self, source: OneByteRegister) {
        println!("LD_u8_internal {:?} <- {:?}", self, source);
    }
}

impl Load<TwoByteRegister> for TwoByteRegister {
    fn LD(self, source: TwoByteRegister) {
        println!("LD_u16_internal {:?} <- {:?}", self, source);
    }
}
LD_u8_immediate A <- 15
LD_u8_internal F <- A
LD_u16_immediate HL <- 3855
LD_u16_internal DC <- HL