dds_bridge/solver/system_info.rs
1//! DDS library version, build, and threading metadata
2
3use dds_bridge_sys as sys;
4use semver::Version;
5
6use core::ffi::{CStr, c_char};
7use core::fmt;
8
9/// OS platform reported by the DDS 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 DDS 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 DDS 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 DDS library and how it was built
61///
62/// Returned by [`Solver::system_info`](super::Solver::system_info). Exposes
63/// the version, hardware configuration (cores, threads, pointer width), and
64/// compile-time choices (OS, compiler, threading model) that DDS was built
65/// with.
66#[derive(Debug, Clone, Copy)]
67pub struct SystemInfo(pub(super) sys::DDSInfo);
68
69impl SystemInfo {
70 /// DDS version
71 #[must_use]
72 pub const fn version(&self) -> Version {
73 #[allow(clippy::cast_sign_loss)]
74 Version::new(
75 self.0.major as u64,
76 self.0.minor as u64,
77 self.0.patch as u64,
78 )
79 }
80
81 /// OS platform DDS was built for
82 #[must_use]
83 pub const fn platform(&self) -> Platform {
84 match self.0.system {
85 1 => Platform::Windows,
86 2 => Platform::Cygwin,
87 3 => Platform::Linux,
88 4 => Platform::Apple,
89 n => Platform::Unknown(n),
90 }
91 }
92
93 /// Pointer size in bits (32 or 64)
94 #[must_use]
95 pub const fn num_bits(&self) -> u32 {
96 #[allow(clippy::cast_sign_loss)]
97 return self.0.numBits as u32;
98 }
99
100 /// C++ compiler DDS was built with
101 #[must_use]
102 pub const fn compiler(&self) -> Compiler {
103 match self.0.compiler {
104 1 => Compiler::MSVC,
105 2 => Compiler::MinGW,
106 3 => Compiler::GCC,
107 4 => Compiler::Clang,
108 n => Compiler::Unknown(n),
109 }
110 }
111
112 /// Threading model DDS was built with
113 ///
114 /// Currently, [`dds_bridge_sys`] only supports [`Threading::STL`] for
115 /// maximum compatibility, minimum code size, and competitive performance.
116 /// Other variants may be activated in the future for specialized use cases
117 /// or platforms.
118 #[must_use]
119 pub const fn threading(&self) -> Threading {
120 match self.0.threading {
121 0 => Threading::None,
122 1 => Threading::Windows,
123 2 => Threading::OpenMP,
124 3 => Threading::GCD,
125 4 => Threading::Boost,
126 5 => Threading::STL,
127 6 => Threading::TBB,
128 n => Threading::Unknown(n),
129 }
130 }
131
132 /// Number of CPU cores detected by DDS
133 #[must_use]
134 pub const fn num_cores(&self) -> usize {
135 #[allow(clippy::cast_sign_loss)]
136 return self.0.numCores as usize;
137 }
138
139 /// Number of threads configured in the DDS thread pool
140 #[must_use]
141 pub const fn num_threads(&self) -> usize {
142 #[allow(clippy::cast_sign_loss)]
143 return self.0.noOfThreads as usize;
144 }
145
146 /// Memory-size description for each thread slot
147 ///
148 /// A string such as `"0 S, 16 L"` where `L` denotes a large transposition
149 /// table and `S` a small one.
150 #[must_use]
151 pub const fn thread_sizes(&self) -> &str {
152 // SAFETY: [DDS fills `threadSizes` with a null-terminated ASCII string.](https://github.com/dds-bridge/dds/blob/d2bc4c2c703941664fc1d73e69caa5233cdeac18/src/System.cpp#L756)
153 unsafe { c_chars_to_str(&self.0.threadSizes) }
154 }
155
156 /// Human-readable summary of the full DDS system configuration
157 #[must_use]
158 pub const fn system_string(&self) -> &str {
159 // SAFETY: [DDS fills `systemString` with a null-terminated ASCII string.](https://github.com/dds-bridge/dds/blob/d2bc4c2c703941664fc1d73e69caa5233cdeac18/src/System.cpp#L773)
160 unsafe { c_chars_to_str(&self.0.systemString) }
161 }
162}
163
164const unsafe fn c_chars_to_str(bytes: &[c_char]) -> &str {
165 unsafe { core::str::from_utf8_unchecked(CStr::from_ptr(bytes.as_ptr()).to_bytes()) }
166}
167
168impl fmt::Display for SystemInfo {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 f.write_str(self.system_string())
171 }
172}