Skip to main content

whiteout/
host.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026 Fernando Sahmkow
3// AUTOGENERATED by tools/codegen/emit_rust.py — do not edit.
4// Regenerate via:  python -m tools.codegen.codegen host --backend rust
5
6#![allow(clippy::too_many_arguments)]
7
8// Which of these a module needs depends on its shapes; the modules that
9// have no span accessors would otherwise trip the unused-import lint.
10#[allow(unused_imports)]
11use crate::support::{BorrowedSlice, Bytes};
12
13/// Known Blizzard game identifiers.
14///
15/// The `Unknown` value is used for games discovered via generic heuristics (e.g. the Windows Uninstall registry scan) that don't match a known title. In that case, inspect the `name` field of the result for the display name.
16#[repr(i32)]
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
18pub enum BlizzardGame {
19    Unknown = 0,
20    WorldOfWarcraft = 1,
21    WorldOfWarcraftClassic = 2,
22    WorldOfWarcraftClassicEra = 3,
23    WarcraftIIBattleNetEdition = 4,
24    WarcraftIIRemastered = 5,
25    WarcraftIII = 6,
26    WarcraftIIIReforged = 7,
27    StarCraft = 8,
28    StarCraftRemastered = 9,
29    StarCraftII = 10,
30    Diablo = 11,
31    DiabloII = 12,
32    DiabloIIResurrected = 13,
33    DiabloIII = 14,
34    DiabloIV = 15,
35    DiabloImmortal = 16,
36    HeroesOfTheStorm = 17,
37    Overwatch2 = 18,
38    Hearthstone = 19,
39    BlizzardArcadeCollection = 20,
40    BattleNet = 21,
41}
42
43impl TryFrom<i32> for BlizzardGame {
44    type Error = crate::Error;
45    fn try_from(v: i32) -> Result<Self, crate::Error> {
46        match v {
47            0 => Ok(BlizzardGame::Unknown),
48            1 => Ok(BlizzardGame::WorldOfWarcraft),
49            2 => Ok(BlizzardGame::WorldOfWarcraftClassic),
50            3 => Ok(BlizzardGame::WorldOfWarcraftClassicEra),
51            4 => Ok(BlizzardGame::WarcraftIIBattleNetEdition),
52            5 => Ok(BlizzardGame::WarcraftIIRemastered),
53            6 => Ok(BlizzardGame::WarcraftIII),
54            7 => Ok(BlizzardGame::WarcraftIIIReforged),
55            8 => Ok(BlizzardGame::StarCraft),
56            9 => Ok(BlizzardGame::StarCraftRemastered),
57            10 => Ok(BlizzardGame::StarCraftII),
58            11 => Ok(BlizzardGame::Diablo),
59            12 => Ok(BlizzardGame::DiabloII),
60            13 => Ok(BlizzardGame::DiabloIIResurrected),
61            14 => Ok(BlizzardGame::DiabloIII),
62            15 => Ok(BlizzardGame::DiabloIV),
63            16 => Ok(BlizzardGame::DiabloImmortal),
64            17 => Ok(BlizzardGame::HeroesOfTheStorm),
65            18 => Ok(BlizzardGame::Overwatch2),
66            19 => Ok(BlizzardGame::Hearthstone),
67            20 => Ok(BlizzardGame::BlizzardArcadeCollection),
68            21 => Ok(BlizzardGame::BattleNet),
69            other => Err(crate::Error::UnknownEnum {
70                name: "BlizzardGame",
71                value: other,
72            }),
73        }
74    }
75}
76
77/// java_package=whiteout.utils — abstract opaque base. Concrete impl: utils::SimpleThreadPool.
78pub struct WorkerPool {
79    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_WorkerPool>,
80}
81
82impl Drop for WorkerPool {
83    fn drop(&mut self) {
84        // SAFETY: `raw` came from a native constructor and Drop runs once.
85        unsafe { ffi::whiteout_host_WorkerPool_delete(self.raw.as_ptr()) }
86    }
87}
88
89impl WorkerPool {
90    /// # Safety
91    /// `raw` must be a live handle this value takes ownership of.
92    #[allow(dead_code)] // used by whichever methods return this type
93    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_WorkerPool) -> Option<Self> {
94        core::ptr::NonNull::new(raw).map(|raw| WorkerPool { raw })
95    }
96}
97
98// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
99// is deliberately NOT implemented — the C++ types make no documented
100// guarantee about concurrent use, and claiming one we haven't verified
101// would be unsound. See `@bind thread_safe` in the plan.
102unsafe impl Send for WorkerPool {}
103
104impl core::fmt::Debug for WorkerPool {
105    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106        f.debug_struct("WorkerPool").finish_non_exhaustive()
107    }
108}
109
110impl WorkerPool {
111    /// Block until every submitted task has completed.
112    pub fn wait_idle(&mut self) {
113        // SAFETY: handle is live for the duration of the call.
114        unsafe {
115            ffi::whiteout_host_WorkerPool_waitIdle(self.raw.as_ptr());
116        }
117    }
118
119    /// Number of worker threads in this pool.
120    pub fn thread_count(&self) -> usize {
121        // SAFETY: handle is live for the duration of the call.
122        unsafe { ffi::whiteout_host_WorkerPool_threadCount(self.raw.as_ptr()) }
123    }
124}
125
126/// java_package=whiteout.utils — abstract file system that resolves files by numeric data ID (e.g. CASC).
127pub struct CascFileSystem {
128    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_CascFileSystem>,
129}
130
131impl Drop for CascFileSystem {
132    fn drop(&mut self) {
133        // SAFETY: `raw` came from a native constructor and Drop runs once.
134        unsafe { ffi::whiteout_host_CascFileSystem_delete(self.raw.as_ptr()) }
135    }
136}
137
138impl CascFileSystem {
139    /// # Safety
140    /// `raw` must be a live handle this value takes ownership of.
141    #[allow(dead_code)] // used by whichever methods return this type
142    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_CascFileSystem) -> Option<Self> {
143        core::ptr::NonNull::new(raw).map(|raw| CascFileSystem { raw })
144    }
145}
146
147// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
148// is deliberately NOT implemented — the C++ types make no documented
149// guarantee about concurrent use, and claiming one we haven't verified
150// would be unsound. See `@bind thread_safe` in the plan.
151unsafe impl Send for CascFileSystem {}
152
153impl core::fmt::Debug for CascFileSystem {
154    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
155        f.debug_struct("CascFileSystem").finish_non_exhaustive()
156    }
157}
158
159impl CascFileSystem {
160    /// Read the entire contents of a file by its numeric data ID.
161    pub fn read_file(&self, file_id: u32) -> Bytes {
162        // SAFETY: handle is live for the duration of the call.
163        unsafe {
164            Bytes::from_raw(ffi::whiteout_host_CascFileSystem_readFile(
165                self.raw.as_ptr(),
166                file_id,
167            ))
168            .unwrap_or_else(Bytes::empty)
169        }
170    }
171
172    /// Resolve a path to a numeric file ID (nullable).
173    pub fn reserve_file_id(&mut self, path: &str) -> Option<u32> {
174        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
175        let mut __v: u32 = 0;
176        // SAFETY: `__v` is a live local, written by the
177        // native side only when it returns 1.
178        let __has = unsafe {
179            ffi::whiteout_host_CascFileSystem_reserveFileId(
180                self.raw.as_ptr(),
181                path_cstr.as_ptr(),
182                &mut __v,
183            )
184        };
185        (__has != 0).then_some(__v)
186    }
187
188    /// Write a file by its numeric data ID. Returns true on success.
189    pub fn write_file(&mut self, file_id: u32, data: &[u8]) -> bool {
190        // SAFETY: handle is live for the duration of the call.
191        unsafe {
192            ffi::whiteout_host_CascFileSystem_writeFile(
193                self.raw.as_ptr(),
194                file_id,
195                data.as_ptr(),
196                data.len(),
197            ) != 0
198        }
199    }
200
201    /// Check if a file with the given data ID exists.
202    pub fn file_exists(&self, file_id: u32) -> bool {
203        // SAFETY: handle is live for the duration of the call.
204        unsafe { ffi::whiteout_host_CascFileSystem_fileExists(self.raw.as_ptr(), file_id) != 0 }
205    }
206}
207
208/// java_package=whiteout.utils — abstract base. Concrete impl: utils::OsFileSystem.
209pub struct VirtualPathFileSystem {
210    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_VirtualPathFileSystem>,
211}
212
213impl Drop for VirtualPathFileSystem {
214    fn drop(&mut self) {
215        // SAFETY: `raw` came from a native constructor and Drop runs once.
216        unsafe { ffi::whiteout_host_VirtualPathFileSystem_delete(self.raw.as_ptr()) }
217    }
218}
219
220impl VirtualPathFileSystem {
221    /// # Safety
222    /// `raw` must be a live handle this value takes ownership of.
223    #[allow(dead_code)] // used by whichever methods return this type
224    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_VirtualPathFileSystem) -> Option<Self> {
225        core::ptr::NonNull::new(raw).map(|raw| VirtualPathFileSystem { raw })
226    }
227}
228
229// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
230// is deliberately NOT implemented — the C++ types make no documented
231// guarantee about concurrent use, and claiming one we haven't verified
232// would be unsound. See `@bind thread_safe` in the plan.
233unsafe impl Send for VirtualPathFileSystem {}
234
235impl core::fmt::Debug for VirtualPathFileSystem {
236    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237        f.debug_struct("VirtualPathFileSystem")
238            .finish_non_exhaustive()
239    }
240}
241
242impl VirtualPathFileSystem {
243    /// Read the entire contents of a file into a byte vector.
244    pub fn read_file(&self, path: &str) -> Bytes {
245        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
246        // SAFETY: handle is live for the duration of the call.
247        unsafe {
248            Bytes::from_raw(ffi::whiteout_host_VirtualPathFileSystem_readFile(
249                self.raw.as_ptr(),
250                path_cstr.as_ptr(),
251            ))
252            .unwrap_or_else(Bytes::empty)
253        }
254    }
255
256    /// Write a file. Returns true on success.
257    pub fn write_file(&mut self, path: &str, data: &[u8]) -> bool {
258        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
259        // SAFETY: handle is live for the duration of the call.
260        unsafe {
261            ffi::whiteout_host_VirtualPathFileSystem_writeFile(
262                self.raw.as_ptr(),
263                path_cstr.as_ptr(),
264                data.as_ptr(),
265                data.len(),
266            ) != 0
267        }
268    }
269
270    /// Check if a file exists at the given path.
271    pub fn file_exists(&self, path: &str) -> bool {
272        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
273        // SAFETY: handle is live for the duration of the call.
274        unsafe {
275            ffi::whiteout_host_VirtualPathFileSystem_fileExists(
276                self.raw.as_ptr(),
277                path_cstr.as_ptr(),
278            ) != 0
279        }
280    }
281}
282
283/// HTTP GET result handed to user callbacks.
284pub struct HttpResponse {
285    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_HttpResponse>,
286}
287
288impl Drop for HttpResponse {
289    fn drop(&mut self) {
290        // SAFETY: `raw` came from a native constructor and Drop runs once.
291        unsafe { ffi::whiteout_host_HttpResponse_delete(self.raw.as_ptr()) }
292    }
293}
294
295impl HttpResponse {
296    /// # Safety
297    /// `raw` must be a live handle this value takes ownership of.
298    #[allow(dead_code)] // used by whichever methods return this type
299    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_HttpResponse) -> Option<Self> {
300        core::ptr::NonNull::new(raw).map(|raw| HttpResponse { raw })
301    }
302}
303
304// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
305// is deliberately NOT implemented — the C++ types make no documented
306// guarantee about concurrent use, and claiming one we haven't verified
307// would be unsound. See `@bind thread_safe` in the plan.
308unsafe impl Send for HttpResponse {}
309
310impl core::fmt::Debug for HttpResponse {
311    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
312        f.debug_struct("HttpResponse").finish_non_exhaustive()
313    }
314}
315
316impl HttpResponse {
317    /// # Panics
318    /// Panics if the native allocation fails.
319    pub fn new() -> Self {
320        // SAFETY: the native constructor returns a live handle; a null here
321        // means the library is unusable.
322        unsafe {
323            let raw = ffi::whiteout_host_HttpResponse_new();
324            Self::from_raw(raw).expect("native HttpResponse allocation failed")
325        }
326    }
327
328    /// HTTP status code (200, 206, 404, …).
329    pub fn status_code(&self) -> i32 {
330        // SAFETY: plain scalar read through a live handle.
331        unsafe { ffi::whiteout_host_HttpResponse_get_statusCode(self.raw.as_ptr()) }
332    }
333
334    pub fn set_status_code(&mut self, value: i32) {
335        // SAFETY: plain scalar write through a live handle.
336        unsafe { ffi::whiteout_host_HttpResponse_set_statusCode(self.raw.as_ptr(), value) }
337    }
338
339    /// Response body.
340    /// Zero-copy view of the underlying `std::vector`.
341    pub fn body(&self) -> &[u8] {
342        // SAFETY: `_data`/`_count` describe one contiguous C++
343        // allocation, borrowed for as long as `self` is.
344        unsafe {
345            let n = ffi::whiteout_host_HttpResponse_get_body_count(self.raw.as_ptr());
346            let p = ffi::whiteout_host_HttpResponse_get_body_data(self.raw.as_ptr());
347            if p.is_null() || n == 0 {
348                &[]
349            } else {
350                core::slice::from_raw_parts(p, n)
351            }
352        }
353    }
354
355    /// Zero-copy mutable view. Resize first — the borrow forbids it after.
356    pub fn body_mut(&mut self) -> &mut [u8] {
357        // SAFETY: as above; `&mut self` rules out aliasing and resizing.
358        unsafe {
359            let n = ffi::whiteout_host_HttpResponse_get_body_count(self.raw.as_ptr());
360            let p = ffi::whiteout_host_HttpResponse_get_body_data(self.raw.as_ptr()) as *mut u8;
361            if p.is_null() || n == 0 {
362                &mut []
363            } else {
364                core::slice::from_raw_parts_mut(p, n)
365            }
366        }
367    }
368
369    pub fn set_body(&mut self, values: &[u8]) {
370        // SAFETY: the native side copies `values` before returning.
371        unsafe {
372            ffi::whiteout_host_HttpResponse_assign_body(
373                self.raw.as_ptr(),
374                values.as_ptr() as *const _,
375                values.len(),
376            )
377        }
378    }
379
380    pub fn resize_body(&mut self, count: usize) {
381        // SAFETY: reallocation is safe here precisely because
382        // `&mut self` means no slice borrow is outstanding.
383        unsafe { ffi::whiteout_host_HttpResponse_resize_body(self.raw.as_ptr(), count) }
384    }
385
386    /// Transport-level error (empty on success).
387    pub fn error(&self) -> String {
388        // SAFETY: the native side hands over an owned CString.
389        unsafe {
390            crate::support::take_string(ffi::whiteout_host_HttpResponse_get_error(
391                self.raw.as_ptr(),
392            ))
393        }
394    }
395
396    pub fn set_error(&mut self, value: &str) {
397        let value = std::ffi::CString::new(value).unwrap_or_default();
398        // SAFETY: the pointer outlives the call.
399        unsafe { ffi::whiteout_host_HttpResponse_set_error(self.raw.as_ptr(), value.as_ptr()) }
400    }
401}
402
403impl Default for HttpResponse {
404    fn default() -> Self {
405        Self::new()
406    }
407}
408
409/// Abstract HTTP handler.  The library calls these methods to fetch CDN data. Users must provide a concrete implementation.
410///
411/// Both methods are pure virtual — async support is mandatory. The handler invokes @p callback exactly once when the request completes (or fails). The callback may be invoked from any thread.
412///
413/// Thread safety: methods may be called concurrently from multiple WorkerPool threads.  The implementation must be thread-safe.
414///
415/// java_package=whiteout.utils — abstract opaque base. Concrete impl: utils::SimpleHttpHandler.
416pub struct HttpHandler {
417    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_HttpHandler>,
418}
419
420impl Drop for HttpHandler {
421    fn drop(&mut self) {
422        // SAFETY: `raw` came from a native constructor and Drop runs once.
423        unsafe { ffi::whiteout_host_HttpHandler_delete(self.raw.as_ptr()) }
424    }
425}
426
427impl HttpHandler {
428    /// # Safety
429    /// `raw` must be a live handle this value takes ownership of.
430    #[allow(dead_code)] // used by whichever methods return this type
431    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_HttpHandler) -> Option<Self> {
432        core::ptr::NonNull::new(raw).map(|raw| HttpHandler { raw })
433    }
434}
435
436// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
437// is deliberately NOT implemented — the C++ types make no documented
438// guarantee about concurrent use, and claiming one we haven't verified
439// would be unsound. See `@bind thread_safe` in the plan.
440unsafe impl Send for HttpHandler {}
441
442impl core::fmt::Debug for HttpHandler {
443    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
444        f.debug_struct("HttpHandler").finish_non_exhaustive()
445    }
446}
447
448impl HttpHandler {
449    /// Reported handler capability flags.
450    pub fn capabilities(&self) -> u32 {
451        // SAFETY: handle is live for the duration of the call.
452        unsafe { ffi::whiteout_host_HttpHandler_capabilities(self.raw.as_ptr()) }
453    }
454}
455
456/// VirtualPathFileSystem implementation backed by the OS filesystem.
457///
458/// All paths passed to readFile() / fileExists() are resolved relative to the root directory supplied at construction time.
459///
460/// Example: utils::OsFileSystem fs("C:/Games/Warcraft III/Data"); auto data = fs.readFile("units/human/arthas/arthas.mdx");
461///
462/// java_package=whiteout.utils
463pub struct OsFileSystem {
464    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_OsFileSystem>,
465}
466
467impl Drop for OsFileSystem {
468    fn drop(&mut self) {
469        // SAFETY: `raw` came from a native constructor and Drop runs once.
470        unsafe { ffi::whiteout_host_OsFileSystem_delete(self.raw.as_ptr()) }
471    }
472}
473
474impl OsFileSystem {
475    /// # Safety
476    /// `raw` must be a live handle this value takes ownership of.
477    #[allow(dead_code)] // used by whichever methods return this type
478    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_OsFileSystem) -> Option<Self> {
479        core::ptr::NonNull::new(raw).map(|raw| OsFileSystem { raw })
480    }
481}
482
483// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
484// is deliberately NOT implemented — the C++ types make no documented
485// guarantee about concurrent use, and claiming one we haven't verified
486// would be unsound. See `@bind thread_safe` in the plan.
487unsafe impl Send for OsFileSystem {}
488
489impl core::fmt::Debug for OsFileSystem {
490    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
491        f.debug_struct("OsFileSystem").finish_non_exhaustive()
492    }
493}
494
495impl OsFileSystem {
496    /// Read a file at `rootPath / path`. Returns an empty vector if not found.
497    pub fn read_file(&self, path: &str) -> Bytes {
498        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
499        // SAFETY: handle is live for the duration of the call.
500        unsafe {
501            Bytes::from_raw(ffi::whiteout_host_OsFileSystem_readFile(
502                self.raw.as_ptr(),
503                path_cstr.as_ptr(),
504            ))
505            .unwrap_or_else(Bytes::empty)
506        }
507    }
508
509    pub fn write_file(&mut self, path: &str, data: &[u8]) -> bool {
510        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
511        // SAFETY: handle is live for the duration of the call.
512        unsafe {
513            ffi::whiteout_host_OsFileSystem_writeFile(
514                self.raw.as_ptr(),
515                path_cstr.as_ptr(),
516                data.as_ptr(),
517                data.len(),
518            ) != 0
519        }
520    }
521
522    pub fn file_exists(&self, path: &str) -> bool {
523        let path_cstr = std::ffi::CString::new(path).unwrap_or_default();
524        // SAFETY: handle is live for the duration of the call.
525        unsafe {
526            ffi::whiteout_host_OsFileSystem_fileExists(self.raw.as_ptr(), path_cstr.as_ptr()) != 0
527        }
528    }
529}
530
531/// Basic CPU worker pool implementation of interfaces::WorkerPool.
532///
533/// Tasks are executed by a fixed number of worker threads created at construction time.
534pub struct SimpleThreadPool {
535    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_SimpleThreadPool>,
536}
537
538impl Drop for SimpleThreadPool {
539    fn drop(&mut self) {
540        // SAFETY: `raw` came from a native constructor and Drop runs once.
541        unsafe { ffi::whiteout_host_SimpleThreadPool_delete(self.raw.as_ptr()) }
542    }
543}
544
545impl SimpleThreadPool {
546    /// # Safety
547    /// `raw` must be a live handle this value takes ownership of.
548    #[allow(dead_code)] // used by whichever methods return this type
549    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_SimpleThreadPool) -> Option<Self> {
550        core::ptr::NonNull::new(raw).map(|raw| SimpleThreadPool { raw })
551    }
552}
553
554// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
555// is deliberately NOT implemented — the C++ types make no documented
556// guarantee about concurrent use, and claiming one we haven't verified
557// would be unsound. See `@bind thread_safe` in the plan.
558unsafe impl Send for SimpleThreadPool {}
559
560impl core::fmt::Debug for SimpleThreadPool {
561    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
562        f.debug_struct("SimpleThreadPool").finish_non_exhaustive()
563    }
564}
565
566impl SimpleThreadPool {
567    /// Block until the pool has no pending or running tasks.
568    pub fn wait_idle(&mut self) {
569        // SAFETY: handle is live for the duration of the call.
570        unsafe {
571            ffi::whiteout_host_SimpleThreadPool_waitIdle(self.raw.as_ptr());
572        }
573    }
574
575    /// Number of worker threads in this pool.
576    pub fn thread_count(&self) -> usize {
577        // SAFETY: handle is live for the duration of the call.
578        unsafe { ffi::whiteout_host_SimpleThreadPool_threadCount(self.raw.as_ptr()) }
579    }
580}
581
582/// Basic HTTP handler with two platform backends: * Windows  — WinHTTP * Other    — libcurl (linked at build time)
583///
584/// Requests are dispatched asynchronously onto an internal thread pool; each worker owns one backend handle and keeps its connection cache warm. Thread-safe: multiple threads may call getAsync / getRangeAsync concurrently.
585pub struct SimpleHttpHandler {
586    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_SimpleHttpHandler>,
587}
588
589impl Drop for SimpleHttpHandler {
590    fn drop(&mut self) {
591        // SAFETY: `raw` came from a native constructor and Drop runs once.
592        unsafe { ffi::whiteout_host_SimpleHttpHandler_delete(self.raw.as_ptr()) }
593    }
594}
595
596impl SimpleHttpHandler {
597    /// # Safety
598    /// `raw` must be a live handle this value takes ownership of.
599    #[allow(dead_code)] // used by whichever methods return this type
600    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_SimpleHttpHandler) -> Option<Self> {
601        core::ptr::NonNull::new(raw).map(|raw| SimpleHttpHandler { raw })
602    }
603}
604
605// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
606// is deliberately NOT implemented — the C++ types make no documented
607// guarantee about concurrent use, and claiming one we haven't verified
608// would be unsound. See `@bind thread_safe` in the plan.
609unsafe impl Send for SimpleHttpHandler {}
610
611impl core::fmt::Debug for SimpleHttpHandler {
612    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
613        f.debug_struct("SimpleHttpHandler").finish_non_exhaustive()
614    }
615}
616
617impl SimpleHttpHandler {
618    /// # Panics
619    /// Panics if the native allocation fails.
620    pub fn new() -> Self {
621        // SAFETY: the native constructor returns a live handle; a null here
622        // means the library is unusable.
623        unsafe {
624            let raw = ffi::whiteout_host_SimpleHttpHandler_new();
625            Self::from_raw(raw).expect("native SimpleHttpHandler allocation failed")
626        }
627    }
628
629    /// Reported handler capability flags.
630    pub fn capabilities(&self) -> u32 {
631        // SAFETY: handle is live for the duration of the call.
632        unsafe { ffi::whiteout_host_SimpleHttpHandler_capabilities(self.raw.as_ptr()) }
633    }
634}
635
636impl Default for SimpleHttpHandler {
637    fn default() -> Self {
638        Self::new()
639    }
640}
641
642/// Thread-safe counter-based completion primitive for grouped jobs.
643///
644/// A JobGroup starts with zero pending jobs. Call add() before submitting work, then call done() once per completed job. wait() blocks until the pending count reaches zero.
645///
646/// Typical usage pattern: 1. add(N) 2. submit N tasks 3. each task calls done() on completion 4. wait() to join the group
647pub struct JobGroup {
648    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_JobGroup>,
649}
650
651impl Drop for JobGroup {
652    fn drop(&mut self) {
653        // SAFETY: `raw` came from a native constructor and Drop runs once.
654        unsafe { ffi::whiteout_host_JobGroup_delete(self.raw.as_ptr()) }
655    }
656}
657
658impl JobGroup {
659    /// # Safety
660    /// `raw` must be a live handle this value takes ownership of.
661    #[allow(dead_code)] // used by whichever methods return this type
662    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_JobGroup) -> Option<Self> {
663        core::ptr::NonNull::new(raw).map(|raw| JobGroup { raw })
664    }
665}
666
667// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
668// is deliberately NOT implemented — the C++ types make no documented
669// guarantee about concurrent use, and claiming one we haven't verified
670// would be unsound. See `@bind thread_safe` in the plan.
671unsafe impl Send for JobGroup {}
672
673impl core::fmt::Debug for JobGroup {
674    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
675        f.debug_struct("JobGroup").finish_non_exhaustive()
676    }
677}
678
679impl JobGroup {
680    /// # Panics
681    /// Panics if the native allocation fails.
682    pub fn new() -> Self {
683        // SAFETY: the native constructor returns a live handle; a null here
684        // means the library is unusable.
685        unsafe {
686            let raw = ffi::whiteout_host_JobGroup_new();
687            Self::from_raw(raw).expect("native JobGroup allocation failed")
688        }
689    }
690
691    /// Increment the number of pending jobs.
692    ///
693    /// @param n Number of jobs to add to the group.
694    pub fn add(&mut self, n: usize) {
695        // SAFETY: handle is live for the duration of the call.
696        unsafe {
697            ffi::whiteout_host_JobGroup_add(self.raw.as_ptr(), n);
698        }
699    }
700
701    /// Mark one pending job as completed.
702    ///
703    /// When the pending count reaches zero, all waiters are notified.
704    ///
705    /// @note done() calls must be balanced with prior add() calls.
706    pub fn done(&mut self) {
707        // SAFETY: handle is live for the duration of the call.
708        unsafe {
709            ffi::whiteout_host_JobGroup_done(self.raw.as_ptr());
710        }
711    }
712
713    /// Java's Object.wait() is final so the generated wrapper would fail to compile; expose as await(). Block until all pending jobs in the group are completed.
714    pub fn await_(&mut self) {
715        // SAFETY: handle is live for the duration of the call.
716        unsafe {
717            ffi::whiteout_host_JobGroup_await(self.raw.as_ptr());
718        }
719    }
720
721    /// Check whether the group has no pending jobs.
722    ///
723    /// @return true if pending count is zero, false otherwise.
724    pub fn is_ready(&self) -> bool {
725        // SAFETY: handle is live for the duration of the call.
726        unsafe { ffi::whiteout_host_JobGroup_isReady(self.raw.as_ptr()) != 0 }
727    }
728}
729
730impl Default for JobGroup {
731    fn default() -> Self {
732        Self::new()
733    }
734}
735
736/// Result entry from findBlizzardGames().
737pub struct BlizzardGameInfo {
738    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_BlizzardGameInfo>,
739}
740
741impl Drop for BlizzardGameInfo {
742    fn drop(&mut self) {
743        // SAFETY: `raw` came from a native constructor and Drop runs once.
744        unsafe { ffi::whiteout_host_BlizzardGameInfo_delete(self.raw.as_ptr()) }
745    }
746}
747
748impl BlizzardGameInfo {
749    /// # Safety
750    /// `raw` must be a live handle this value takes ownership of.
751    #[allow(dead_code)] // used by whichever methods return this type
752    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_BlizzardGameInfo) -> Option<Self> {
753        core::ptr::NonNull::new(raw).map(|raw| BlizzardGameInfo { raw })
754    }
755}
756
757// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
758// is deliberately NOT implemented — the C++ types make no documented
759// guarantee about concurrent use, and claiming one we haven't verified
760// would be unsound. See `@bind thread_safe` in the plan.
761unsafe impl Send for BlizzardGameInfo {}
762
763impl core::fmt::Debug for BlizzardGameInfo {
764    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
765        f.debug_struct("BlizzardGameInfo").finish_non_exhaustive()
766    }
767}
768
769impl BlizzardGameInfo {
770    /// # Panics
771    /// Panics if the native allocation fails.
772    pub fn new() -> Self {
773        // SAFETY: the native constructor returns a live handle; a null here
774        // means the library is unusable.
775        unsafe {
776            let raw = ffi::whiteout_host_BlizzardGameInfo_new();
777            Self::from_raw(raw).expect("native BlizzardGameInfo allocation failed")
778        }
779    }
780
781    /// Identified game. `Unknown` if not recognized.
782    pub fn game(&self) -> BlizzardGame {
783        // SAFETY: scalar read; the discriminant is validated below.
784        unsafe { ffi::whiteout_host_BlizzardGameInfo_get_game(self.raw.as_ptr()) }
785            .try_into()
786            .expect("unknown enum discriminant from the native library")
787    }
788
789    pub fn set_game(&mut self, value: BlizzardGame) {
790        // SAFETY: scalar write through a live handle.
791        unsafe { ffi::whiteout_host_BlizzardGameInfo_set_game(self.raw.as_ptr(), value as i32) }
792    }
793
794    /// Human-readable display name.
795    pub fn name(&self) -> String {
796        // SAFETY: the native side hands over an owned CString.
797        unsafe {
798            crate::support::take_string(ffi::whiteout_host_BlizzardGameInfo_get_name(
799                self.raw.as_ptr(),
800            ))
801        }
802    }
803
804    pub fn set_name(&mut self, value: &str) {
805        let value = std::ffi::CString::new(value).unwrap_or_default();
806        // SAFETY: the pointer outlives the call.
807        unsafe { ffi::whiteout_host_BlizzardGameInfo_set_name(self.raw.as_ptr(), value.as_ptr()) }
808    }
809
810    /// Install directory path.
811    pub fn path(&self) -> String {
812        // SAFETY: the native side hands over an owned CString.
813        unsafe {
814            crate::support::take_string(ffi::whiteout_host_BlizzardGameInfo_get_path(
815                self.raw.as_ptr(),
816            ))
817        }
818    }
819
820    pub fn set_path(&mut self, value: &str) {
821        let value = std::ffi::CString::new(value).unwrap_or_default();
822        // SAFETY: the pointer outlives the call.
823        unsafe { ffi::whiteout_host_BlizzardGameInfo_set_path(self.raw.as_ptr(), value.as_ptr()) }
824    }
825}
826
827impl Default for BlizzardGameInfo {
828    fn default() -> Self {
829        Self::new()
830    }
831}
832
833/// Opaque handle around `std::vector<BlizzardGameInfo>` returned by `BlizzardGameFinder::findAll()`. Iterate via size() + at(index).
834pub struct BlizzardGameInfoList {
835    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_BlizzardGameInfoList>,
836}
837
838impl Drop for BlizzardGameInfoList {
839    fn drop(&mut self) {
840        // SAFETY: `raw` came from a native constructor and Drop runs once.
841        unsafe { ffi::whiteout_host_BlizzardGameInfoList_delete(self.raw.as_ptr()) }
842    }
843}
844
845impl BlizzardGameInfoList {
846    /// # Safety
847    /// `raw` must be a live handle this value takes ownership of.
848    #[allow(dead_code)] // used by whichever methods return this type
849    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_BlizzardGameInfoList) -> Option<Self> {
850        core::ptr::NonNull::new(raw).map(|raw| BlizzardGameInfoList { raw })
851    }
852}
853
854// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
855// is deliberately NOT implemented — the C++ types make no documented
856// guarantee about concurrent use, and claiming one we haven't verified
857// would be unsound. See `@bind thread_safe` in the plan.
858unsafe impl Send for BlizzardGameInfoList {}
859
860impl core::fmt::Debug for BlizzardGameInfoList {
861    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
862        f.debug_struct("BlizzardGameInfoList")
863            .finish_non_exhaustive()
864    }
865}
866
867impl BlizzardGameInfoList {
868    /// Number of game entries in the list.
869    pub fn size(&self) -> usize {
870        // SAFETY: handle is live for the duration of the call.
871        unsafe { ffi::whiteout_host_BlizzardGameInfoList_size(self.raw.as_ptr()) }
872    }
873
874    /// Borrowed reference to entry at @p index. Valid until this list is destroyed.
875    pub fn at(&self, index: usize) -> Option<BlizzardGameInfo> {
876        // SAFETY: handle is live for the duration of the call.
877        unsafe {
878            BlizzardGameInfo::from_raw(ffi::whiteout_host_BlizzardGameInfoList_at(
879                self.raw.as_ptr(),
880                index,
881            ))
882        }
883    }
884}
885
886/// Static-method facade around the free functions above so they bind through the class-method codegen path.
887pub struct BlizzardGameFinder {
888    pub(crate) raw: core::ptr::NonNull<ffi::whiteout_BlizzardGameFinder>,
889}
890
891impl Drop for BlizzardGameFinder {
892    fn drop(&mut self) {
893        // SAFETY: `raw` came from a native constructor and Drop runs once.
894        unsafe { ffi::whiteout_host_BlizzardGameFinder_delete(self.raw.as_ptr()) }
895    }
896}
897
898impl BlizzardGameFinder {
899    /// # Safety
900    /// `raw` must be a live handle this value takes ownership of.
901    #[allow(dead_code)] // used by whichever methods return this type
902    pub(crate) unsafe fn from_raw(raw: *mut ffi::whiteout_BlizzardGameFinder) -> Option<Self> {
903        core::ptr::NonNull::new(raw).map(|raw| BlizzardGameFinder { raw })
904    }
905}
906
907// SAFETY: handles are plain heap pointers with no thread affinity. `Sync`
908// is deliberately NOT implemented — the C++ types make no documented
909// guarantee about concurrent use, and claiming one we haven't verified
910// would be unsound. See `@bind thread_safe` in the plan.
911unsafe impl Send for BlizzardGameFinder {}
912
913impl core::fmt::Debug for BlizzardGameFinder {
914    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
915        f.debug_struct("BlizzardGameFinder").finish_non_exhaustive()
916    }
917}
918
919impl BlizzardGameFinder {
920    /// Discover installed Blizzard games. See `findBlizzardGames()`.
921    pub fn find_all() -> Option<BlizzardGameInfoList> {
922        // SAFETY: handle is live for the duration of the call.
923        unsafe { BlizzardGameInfoList::from_raw(ffi::whiteout_host_BlizzardGameFinder_findAll()) }
924    }
925
926    /// Map a display name to a BlizzardGame enum. See `blizzardGameFromName()`.
927    pub fn from_name(name: &str) -> BlizzardGame {
928        let name_cstr = std::ffi::CString::new(name).unwrap_or_default();
929        // SAFETY: handle is live for the duration of the call.
930        unsafe {
931            BlizzardGame::try_from(ffi::whiteout_host_BlizzardGameFinder_fromName(
932                name_cstr.as_ptr(),
933            ))
934            .expect("unknown enum discriminant from the native library (ABI version skew)")
935        }
936    }
937
938    /// Get the canonical display name for a known game. See `blizzardGameToName()`. Returns empty string for Unknown.
939    pub fn to_name(game: BlizzardGame) -> String {
940        // SAFETY: handle is live for the duration of the call.
941        unsafe {
942            crate::support::take_string(ffi::whiteout_host_BlizzardGameFinder_toName(game as i32))
943        }
944    }
945}
946
947#[doc(hidden)]
948pub mod ffi {
949    #![allow(missing_debug_implementations)]
950
951    #[allow(unused_imports)]
952    use crate::support::{RawBytes, RawCString};
953
954    #[repr(C)]
955    pub struct whiteout_WorkerPool {
956        _private: [u8; 0],
957    }
958    #[repr(C)]
959    pub struct whiteout_CascFileSystem {
960        _private: [u8; 0],
961    }
962    #[repr(C)]
963    pub struct whiteout_VirtualPathFileSystem {
964        _private: [u8; 0],
965    }
966    #[repr(C)]
967    pub struct whiteout_HttpResponse {
968        _private: [u8; 0],
969    }
970    #[repr(C)]
971    pub struct whiteout_HttpHandler {
972        _private: [u8; 0],
973    }
974    #[repr(C)]
975    pub struct whiteout_OsFileSystem {
976        _private: [u8; 0],
977    }
978    #[repr(C)]
979    pub struct whiteout_SimpleThreadPool {
980        _private: [u8; 0],
981    }
982    #[repr(C)]
983    pub struct whiteout_SimpleHttpHandler {
984        _private: [u8; 0],
985    }
986    #[repr(C)]
987    pub struct whiteout_JobGroup {
988        _private: [u8; 0],
989    }
990    #[repr(C)]
991    pub struct whiteout_BlizzardGameInfo {
992        _private: [u8; 0],
993    }
994    #[repr(C)]
995    pub struct whiteout_BlizzardGameInfoList {
996        _private: [u8; 0],
997    }
998    #[repr(C)]
999    pub struct whiteout_BlizzardGameFinder {
1000        _private: [u8; 0],
1001    }
1002
1003    extern "C" {
1004        // WorkerPool
1005        pub fn whiteout_host_WorkerPool_delete(self_: *mut whiteout_WorkerPool);
1006        pub fn whiteout_host_WorkerPool_waitIdle(self_: *mut whiteout_WorkerPool);
1007        pub fn whiteout_host_WorkerPool_threadCount(self_: *mut whiteout_WorkerPool) -> usize;
1008        // CascFileSystem
1009        pub fn whiteout_host_CascFileSystem_delete(self_: *mut whiteout_CascFileSystem);
1010        pub fn whiteout_host_CascFileSystem_readFile(
1011            self_: *mut whiteout_CascFileSystem,
1012            file_id: u32,
1013        ) -> RawBytes;
1014        pub fn whiteout_host_CascFileSystem_reserveFileId(
1015            self_: *mut whiteout_CascFileSystem,
1016            path: *const core::ffi::c_char,
1017            out_value: *mut u32,
1018        ) -> i32;
1019        pub fn whiteout_host_CascFileSystem_writeFile(
1020            self_: *mut whiteout_CascFileSystem,
1021            file_id: u32,
1022            data: *const u8,
1023            data_size: usize,
1024        ) -> i32;
1025        pub fn whiteout_host_CascFileSystem_fileExists(
1026            self_: *mut whiteout_CascFileSystem,
1027            file_id: u32,
1028        ) -> i32;
1029        // VirtualPathFileSystem
1030        pub fn whiteout_host_VirtualPathFileSystem_delete(
1031            self_: *mut whiteout_VirtualPathFileSystem,
1032        );
1033        pub fn whiteout_host_VirtualPathFileSystem_readFile(
1034            self_: *mut whiteout_VirtualPathFileSystem,
1035            path: *const core::ffi::c_char,
1036        ) -> RawBytes;
1037        pub fn whiteout_host_VirtualPathFileSystem_writeFile(
1038            self_: *mut whiteout_VirtualPathFileSystem,
1039            path: *const core::ffi::c_char,
1040            data: *const u8,
1041            data_size: usize,
1042        ) -> i32;
1043        pub fn whiteout_host_VirtualPathFileSystem_fileExists(
1044            self_: *mut whiteout_VirtualPathFileSystem,
1045            path: *const core::ffi::c_char,
1046        ) -> i32;
1047        // HttpResponse
1048        pub fn whiteout_host_HttpResponse_new() -> *mut whiteout_HttpResponse;
1049        pub fn whiteout_host_HttpResponse_delete(self_: *mut whiteout_HttpResponse);
1050        pub fn whiteout_host_HttpResponse_get_statusCode(self_: *mut whiteout_HttpResponse) -> i32;
1051        pub fn whiteout_host_HttpResponse_set_statusCode(
1052            self_: *mut whiteout_HttpResponse,
1053            value: i32,
1054        );
1055        pub fn whiteout_host_HttpResponse_get_body_count(
1056            self_: *mut whiteout_HttpResponse,
1057        ) -> usize;
1058        pub fn whiteout_host_HttpResponse_resize_body(
1059            self_: *mut whiteout_HttpResponse,
1060            count: usize,
1061        );
1062        pub fn whiteout_host_HttpResponse_get_body_data(
1063            self_: *mut whiteout_HttpResponse,
1064        ) -> *const u8;
1065        pub fn whiteout_host_HttpResponse_assign_body(
1066            self_: *mut whiteout_HttpResponse,
1067            data: *const u8,
1068            count: usize,
1069        );
1070        pub fn whiteout_host_HttpResponse_get_error(
1071            self_: *mut whiteout_HttpResponse,
1072        ) -> RawCString;
1073        pub fn whiteout_host_HttpResponse_set_error(
1074            self_: *mut whiteout_HttpResponse,
1075            value: *const core::ffi::c_char,
1076        );
1077        // HttpHandler
1078        pub fn whiteout_host_HttpHandler_delete(self_: *mut whiteout_HttpHandler);
1079        pub fn whiteout_host_HttpHandler_capabilities(self_: *mut whiteout_HttpHandler) -> u32;
1080        // OsFileSystem
1081        pub fn whiteout_host_OsFileSystem_new_rootPath(
1082            _0: *mut core::ffi::c_void,
1083        ) -> *mut whiteout_OsFileSystem;
1084        pub fn whiteout_host_OsFileSystem_delete(self_: *mut whiteout_OsFileSystem);
1085        pub fn whiteout_host_OsFileSystem_readFile(
1086            self_: *mut whiteout_OsFileSystem,
1087            path: *const core::ffi::c_char,
1088        ) -> RawBytes;
1089        pub fn whiteout_host_OsFileSystem_writeFile(
1090            self_: *mut whiteout_OsFileSystem,
1091            path: *const core::ffi::c_char,
1092            data: *const u8,
1093            data_size: usize,
1094        ) -> i32;
1095        pub fn whiteout_host_OsFileSystem_fileExists(
1096            self_: *mut whiteout_OsFileSystem,
1097            path: *const core::ffi::c_char,
1098        ) -> i32;
1099        // SimpleThreadPool
1100        pub fn whiteout_host_SimpleThreadPool_new_nThreads(
1101            _0: *mut core::ffi::c_void,
1102        ) -> *mut whiteout_SimpleThreadPool;
1103        pub fn whiteout_host_SimpleThreadPool_delete(self_: *mut whiteout_SimpleThreadPool);
1104        pub fn whiteout_host_SimpleThreadPool_waitIdle(self_: *mut whiteout_SimpleThreadPool);
1105        pub fn whiteout_host_SimpleThreadPool_threadCount(
1106            self_: *mut whiteout_SimpleThreadPool,
1107        ) -> usize;
1108        // SimpleHttpHandler
1109        pub fn whiteout_host_SimpleHttpHandler_new() -> *mut whiteout_SimpleHttpHandler;
1110        pub fn whiteout_host_SimpleHttpHandler_new_nThreads(
1111            _0: *mut core::ffi::c_void,
1112        ) -> *mut whiteout_SimpleHttpHandler;
1113        pub fn whiteout_host_SimpleHttpHandler_delete(self_: *mut whiteout_SimpleHttpHandler);
1114        pub fn whiteout_host_SimpleHttpHandler_capabilities(
1115            self_: *mut whiteout_SimpleHttpHandler,
1116        ) -> u32;
1117        // JobGroup
1118        pub fn whiteout_host_JobGroup_new() -> *mut whiteout_JobGroup;
1119        pub fn whiteout_host_JobGroup_delete(self_: *mut whiteout_JobGroup);
1120        pub fn whiteout_host_JobGroup_add(self_: *mut whiteout_JobGroup, n: usize);
1121        pub fn whiteout_host_JobGroup_done(self_: *mut whiteout_JobGroup);
1122        pub fn whiteout_host_JobGroup_await(self_: *mut whiteout_JobGroup);
1123        pub fn whiteout_host_JobGroup_isReady(self_: *mut whiteout_JobGroup) -> i32;
1124        // BlizzardGameInfo
1125        pub fn whiteout_host_BlizzardGameInfo_new() -> *mut whiteout_BlizzardGameInfo;
1126        pub fn whiteout_host_BlizzardGameInfo_delete(self_: *mut whiteout_BlizzardGameInfo);
1127        pub fn whiteout_host_BlizzardGameInfo_get_game(
1128            self_: *mut whiteout_BlizzardGameInfo,
1129        ) -> i32;
1130        pub fn whiteout_host_BlizzardGameInfo_set_game(
1131            self_: *mut whiteout_BlizzardGameInfo,
1132            value: i32,
1133        );
1134        pub fn whiteout_host_BlizzardGameInfo_get_name(
1135            self_: *mut whiteout_BlizzardGameInfo,
1136        ) -> RawCString;
1137        pub fn whiteout_host_BlizzardGameInfo_set_name(
1138            self_: *mut whiteout_BlizzardGameInfo,
1139            value: *const core::ffi::c_char,
1140        );
1141        pub fn whiteout_host_BlizzardGameInfo_get_path(
1142            self_: *mut whiteout_BlizzardGameInfo,
1143        ) -> RawCString;
1144        pub fn whiteout_host_BlizzardGameInfo_set_path(
1145            self_: *mut whiteout_BlizzardGameInfo,
1146            value: *const core::ffi::c_char,
1147        );
1148        // BlizzardGameInfoList
1149        pub fn whiteout_host_BlizzardGameInfoList_delete(self_: *mut whiteout_BlizzardGameInfoList);
1150        pub fn whiteout_host_BlizzardGameInfoList_size(
1151            self_: *mut whiteout_BlizzardGameInfoList,
1152        ) -> usize;
1153        pub fn whiteout_host_BlizzardGameInfoList_at(
1154            self_: *mut whiteout_BlizzardGameInfoList,
1155            index: usize,
1156        ) -> *mut whiteout_BlizzardGameInfo;
1157        // BlizzardGameFinder
1158        pub fn whiteout_host_BlizzardGameFinder_delete(self_: *mut whiteout_BlizzardGameFinder);
1159        pub fn whiteout_host_BlizzardGameFinder_findAll() -> *mut whiteout_BlizzardGameInfoList;
1160        pub fn whiteout_host_BlizzardGameFinder_fromName(name: *const core::ffi::c_char) -> i32;
1161        pub fn whiteout_host_BlizzardGameFinder_toName(game: i32) -> RawCString;
1162    }
1163}