Skip to main content

ddss/
system_info.rs

1//! ddss library version, build, and threading metadata
2
3use ddss_sys as sys;
4use semver::Version;
5
6use core::ffi::{CStr, c_char};
7use core::fmt;
8
9/// OS platform reported by the ddss library
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum Platform {
12    /// Microsoft Windows
13    Windows,
14    /// Cygwin (Windows POSIX layer)
15    Cygwin,
16    /// Linux
17    Linux,
18    /// Apple (macOS / iOS)
19    Apple,
20    /// Unknown or unrecognized platform
21    Unknown(i32),
22}
23
24/// C++ compiler used to build the ddss library
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum Compiler {
27    /// Microsoft Visual C++
28    MSVC,
29    /// MinGW
30    MinGW,
31    /// GNU g++
32    GCC,
33    /// Clang
34    Clang,
35    /// Unknown or unrecognized compiler
36    Unknown(i32),
37}
38
39/// Threading model used by the ddss library
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
41pub enum Threading {
42    /// No threading
43    None,
44    /// Windows native threads
45    Windows,
46    /// OpenMP
47    OpenMP,
48    /// Grand Central Dispatch (Apple)
49    GCD,
50    /// Boost.Thread
51    Boost,
52    /// C++ standard library threads (`std::thread`)
53    STL,
54    /// Intel Threading Building Blocks
55    TBB,
56    /// Unknown or experimental threading model
57    Unknown(i32),
58}
59
60/// Information about the ddss library and how it was built
61///
62/// Returned by [`system_info`](super::system_info).  Exposes the version,
63/// hardware configuration (cores, threads, pointer width), and compile-time
64/// choices (OS, compiler, threading model) that ddss was built with.
65#[derive(Debug, Clone, Copy)]
66pub struct SystemInfo(pub(super) sys::DDSInfo);
67
68impl SystemInfo {
69    /// ddss version
70    #[must_use]
71    pub const fn version(&self) -> Version {
72        #[allow(clippy::cast_sign_loss)]
73        Version::new(
74            self.0.major as u64,
75            self.0.minor as u64,
76            self.0.patch as u64,
77        )
78    }
79
80    /// OS platform ddss was built for
81    #[must_use]
82    pub const fn platform(&self) -> Platform {
83        match self.0.system {
84            1 => Platform::Windows,
85            2 => Platform::Cygwin,
86            3 => Platform::Linux,
87            4 => Platform::Apple,
88            n => Platform::Unknown(n),
89        }
90    }
91
92    /// Pointer size in bits (32 or 64)
93    #[must_use]
94    pub const fn num_bits(&self) -> u32 {
95        #[allow(clippy::cast_sign_loss)]
96        return self.0.numBits as u32;
97    }
98
99    /// C++ compiler ddss was built with
100    #[must_use]
101    pub const fn compiler(&self) -> Compiler {
102        match self.0.compiler {
103            1 => Compiler::MSVC,
104            2 => Compiler::MinGW,
105            3 => Compiler::GCC,
106            4 => Compiler::Clang,
107            n => Compiler::Unknown(n),
108        }
109    }
110
111    /// Threading model ddss was built with
112    ///
113    /// `ddss-sys` always builds with [`Threading::STL`] (`DDS_THREADS_STL`).
114    #[must_use]
115    pub const fn threading(&self) -> Threading {
116        match self.0.threading {
117            0 => Threading::None,
118            1 => Threading::Windows,
119            2 => Threading::OpenMP,
120            3 => Threading::GCD,
121            4 => Threading::Boost,
122            5 => Threading::STL,
123            6 => Threading::TBB,
124            n => Threading::Unknown(n),
125        }
126    }
127
128    /// Number of CPU cores detected by ddss
129    #[must_use]
130    pub const fn num_cores(&self) -> usize {
131        #[allow(clippy::cast_sign_loss)]
132        return self.0.numCores as usize;
133    }
134
135    /// Number of threads configured in the ddss thread pool
136    #[must_use]
137    pub const fn num_threads(&self) -> usize {
138        #[allow(clippy::cast_sign_loss)]
139        return self.0.noOfThreads as usize;
140    }
141
142    /// Memory-size description for each thread slot
143    ///
144    /// A string such as `"0 S, 16 L"` where `L` denotes a large transposition
145    /// table and `S` a small one.
146    #[must_use]
147    pub const fn thread_sizes(&self) -> &str {
148        // SAFETY: ddss fills `threadSizes` with a null-terminated ASCII string.
149        unsafe { c_chars_to_str(&self.0.threadSizes) }
150    }
151
152    /// Human-readable summary of the full ddss system configuration
153    #[must_use]
154    pub const fn system_string(&self) -> &str {
155        // SAFETY: ddss fills `systemString` with a null-terminated ASCII string.
156        unsafe { c_chars_to_str(&self.0.systemString) }
157    }
158}
159
160const unsafe fn c_chars_to_str(bytes: &[c_char]) -> &str {
161    unsafe { core::str::from_utf8_unchecked(CStr::from_ptr(bytes.as_ptr()).to_bytes()) }
162}
163
164impl fmt::Display for SystemInfo {
165    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166        f.write_str(self.system_string())
167    }
168}