1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Ignore style warnings for for byondapi-c bindings
#![allow(
    clippy::missing_safety_doc,
    non_upper_case_globals,
    non_camel_case_types,
    non_snake_case
)]
use std::ops::Deref;

#[cfg(not(target_pointer_width = "32"))]
compile_error!("BYOND API only functions with 32-bit targets");

#[cfg(not(target_arch = "x86"))]
compile_error!("BYOND API only functions on x86 targets");

#[cfg(not(any(target_os = "linux", target_os = "windows")))]
compile_error!("BYOND API only supports Windows and Linux");

// Include byondapi-c bindings (generated by build.rs)
#[allow(dead_code, rustdoc::broken_intra_doc_links)]
mod byond_rawbind {
    #[cfg(feature = "byond-515-1621")]
    include!(concat!(env!("OUT_DIR"), "/bindings_515_1621.rs"));
}

#[cfg(doc)]
pub use byond_rawbind::ByondApi as RawByondApi;

/// we must simply hope this never changes
mod version {
    use super::byond_rawbind::u4c;

    pub unsafe fn get_byond_version(library: &libloading::Library) -> (u32, u32) {
        let Byond_GetVersion: unsafe extern "C" fn(version: *mut u4c, build: *mut u4c) = library
            .get(b"Byond_GetVersion\0")
            .map(|sym| *sym)
            .expect("Failed to find Byond_GetVersion");

        let mut version = 0;
        let mut build = 0;

        Byond_GetVersion(&mut version, &mut build);

        (version, build)
    }
}

pub struct ByondApi {
    internal: byond_rawbind::ByondApi,
    version: (u32, u32),
}

unsafe impl Sync for ByondApi {}
unsafe impl Send for ByondApi {}

impl ByondApi {
    pub unsafe fn init_from_library<L>(library: L) -> Result<ByondApi, libloading::Error>
    where
        L: Into<::libloading::Library>,
    {
        let lib = library.into();
        let version = version::get_byond_version(&lib);

        let internal = byond_rawbind::ByondApi::from_library(lib)?;

        Ok(ByondApi { internal, version })
    }

    pub fn get_version(&self) -> (u32, u32) {
        self.version
    }
}

impl Deref for ByondApi {
    type Target = byond_rawbind::ByondApi;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.internal
    }
}

// Stabilized types
pub use byond_rawbind::s1c;
pub use byond_rawbind::s1cMAX;
pub use byond_rawbind::s1cMIN;
pub use byond_rawbind::s2c;
pub use byond_rawbind::s2cMAX;
pub use byond_rawbind::s2cMIN;
pub use byond_rawbind::s4c;
pub use byond_rawbind::s4cMAX;
pub use byond_rawbind::s4cMIN;
pub use byond_rawbind::s8c;
pub use byond_rawbind::u1c;
pub use byond_rawbind::u2c;
pub use byond_rawbind::u4c;
pub use byond_rawbind::u4cOrPointer;
pub use byond_rawbind::u8c;
pub use byond_rawbind::ByondCallback;
pub use byond_rawbind::ByondValueData;
pub use byond_rawbind::ByondValueType;
pub use byond_rawbind::CByondValue;
pub use byond_rawbind::CByondXYZ;