D lang to Rust file translate

Hi guys. I translate a script from D to Rust. You can check if everything is correct?
D Source file
Rust source file

First, one way you can replicate PAWN_CELL_SIZE is like so:

macro_rules! PAWN_CELL_SIZE {
    (16) => {
        pub const PAWN_CELL_SIZE: usize = 16;
        pub type cell = i16;
        pub type ucell = u16;
    };
    (32) => {
        pub const PAWN_CELL_SIZE: usize = 32;
        pub type cell = i32;
        pub type ucell = u32;
    };
    (64) => {
        pub const PAWN_CELL_SIZE: usize = 64;
        pub type cell = i64;
        pub type ucell = u64;
    };
}

PAWN_CELL_SIZE!(32);

Also, you can use #![allow(non_camel_case_types)] at the top to disable the lint module- or crate-wide.

I believe your enum translation is wrong. Assuming I remember correctly, D allows you to store any value of the base type you want in an enum. Rust absolutely does not allow this. The closest you can currently get with Rust would be to have something like:

pub type AmxData = u32;
pub const USERNUM: AmxData = 4;
...

Or you can manually namespace the constants if you want:

pub type AmxData = u32;

#[allow(non_snake_case)]
pub mod AmxDataC {
    use super::AmxData;
    pub const USERNUM: AmxData = 4;
    ...
}

Your function pointers should all be Option<unsafe extern "C" fn (...) -> ...>. Function pointers in Rust cannot be null, and unless you know for a fact that the callbacks will go into Rust code, you should also assume they're unsafe.

I'm not sure if you did it deliberately, but your translation of AmxDebug_fn and AmxNative_fn is both right and wrong. It's wrong in that a ref T in D is mutable, whereas &T in Rust is immutable. It's right in that ref T in D is not &mut T in Rust, because &mut T in Rust cannot be aliased, whereas I believe it can in D. &T can be aliased, but doesn't allow mutation.

I suspect the closest translation for ref T would be &UnsafeCell<T>... but I don't know if that's actually guaranteed or not. Unless someone can confirm that it is, you might be better off using *mut T and noting in the code that it won't be null.

For Amx::usertags, isn't D long 64-bit? If so, should be i64 in Rust.

I don't know if you're asking a question about AmxNativeInfo::name. immutable in D is const in Rust. There's no equivalent to D's const.

Again, more long -> i32. I just checked, and long is 64-bit, so all long -> i32 conversions are wrong.

You should be able to translate char in D to u8 in Rust.

I just saw AmxTagInfo::name. Ok, look... I think that will technically work, but you are not allowed to assume that. The layout of &str is not guaranteed, so far as I know, so it could break at any time. It would be safer to write a type that represents a D string and just translates the fields into a Rust slice. Look up the Deref trait, and std::slice::from_raw_parts.

Oh! And D slices can be null, &str cannot be null. So yeah, that translation is wrong.

Still, so close. Woulda been cool. :slight_smile:

Again, another enum. D enums and Rust enums aren't the same.

4 Likes