asr/runtime/
sys.rs

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
use core::num::NonZeroU64;

use crate::Address;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct NonZeroAddress(pub NonZeroU64);

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct Process(NonZeroU64);

/// A process id is a unique identifier for a process. It is not guaranteed to
/// be the same across multiple runs of the same process. It is only guaranteed
/// to be unique for the duration of the process. This matches the operating
/// system's definition of a process id.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct ProcessId(pub u64);

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct TimerState(u32);

impl TimerState {
    /// The timer is not running.
    pub const NOT_RUNNING: Self = Self(0);
    /// The timer is running.
    pub const RUNNING: Self = Self(1);
    /// The timer started but got paused. This is separate from the game
    /// time being paused. Game time may even always be paused.
    pub const PAUSED: Self = Self(2);
    /// The timer has ended, but didn't get reset yet.
    pub const ENDED: Self = Self(3);
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct SettingsMap(NonZeroU64);

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct SettingsList(NonZeroU64);

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct SettingValue(NonZeroU64);

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct SettingValueType(u32);

impl SettingValueType {
    /// The setting value is a settings map.
    pub const MAP: Self = Self(1);
    /// The setting value is a settings list.
    pub const LIST: Self = Self(2);
    /// The setting value is a boolean.
    pub const BOOL: Self = Self(3);
    /// The setting value is a 64-bit signed integer.
    pub const I64: Self = Self(4);
    /// The setting value is a 64-bit floating point number.
    pub const F64: Self = Self(5);
    /// The setting value is a string.
    pub const STRING: Self = Self(6);
}

extern "C" {
    /// Gets the state that the timer currently is in.
    pub fn timer_get_state() -> TimerState;

    /// Starts the timer.
    pub fn timer_start();
    /// Splits the current segment.
    pub fn timer_split();
    /// Skips the current split.
    pub fn timer_skip_split();
    /// Undoes the previous split.
    pub fn timer_undo_split();
    /// Resets the timer.
    pub fn timer_reset();
    /// Sets a custom key value pair. This may be arbitrary information that the
    /// auto splitter wants to provide for visualization. The pointers need to
    /// point to valid UTF-8 encoded text with the respective given length.
    pub fn timer_set_variable(
        key_ptr: *const u8,
        key_len: usize,
        value_ptr: *const u8,
        value_len: usize,
    );

    /// Sets the game time.
    pub fn timer_set_game_time(secs: i64, nanos: i32);
    /// Pauses the game time. This does not pause the timer, only the
    /// automatic flow of time for the game time.
    pub fn timer_pause_game_time();
    /// Resumes the game time. This does not resume the timer, only the
    /// automatic flow of time for the game time.
    pub fn timer_resume_game_time();

    /// Attaches to a process based on its name. The pointer needs to point to
    /// valid UTF-8 encoded text with the given length.
    pub fn process_attach(name_ptr: *const u8, name_len: usize) -> Option<Process>;
    /// Attaches to a process based on its process id.
    pub fn process_attach_by_pid(pid: ProcessId) -> Option<Process>;
    /// Detaches from a process.
    pub fn process_detach(process: Process);
    /// Lists processes based on their name. The name pointer needs to point to
    /// valid UTF-8 encoded text with the given length. Returns `false` if
    /// listing the processes failed. If it was successful, the buffer is now
    /// filled with the process ids. They are in no specific order. The
    /// `list_len_ptr` will be updated to the amount of process ids that were
    /// found. If this is larger than the original value provided, the buffer
    /// provided was too small and not all process ids could be stored. This is
    /// still considered successful and can optionally be treated as an error
    /// condition by the caller by checking if the length increased and
    /// potentially reallocating a larger buffer. If the length decreased after
    /// the call, the buffer was larger than needed and the remaining entries
    /// are untouched.
    pub fn process_list_by_name(
        name_ptr: *const u8,
        name_len: usize,
        list_ptr: *mut ProcessId,
        list_len_ptr: *mut usize,
    ) -> bool;
    /// Checks whether is a process is still open. You should detach from a
    /// process and stop using it if this returns `false`.
    pub fn process_is_open(process: Process) -> bool;
    /// Reads memory from a process at the address given. This will write
    /// the memory to the buffer given. Returns `false` if this fails.
    pub fn process_read(
        process: Process,
        address: Address,
        buf_ptr: *mut u8,
        buf_len: usize,
    ) -> bool;
    /// Gets the address of a module in a process. The pointer needs to point to
    /// valid UTF-8 encoded text with the given length.
    pub fn process_get_module_address(
        process: Process,
        name_ptr: *const u8,
        name_len: usize,
    ) -> Option<NonZeroAddress>;
    /// Gets the size of a module in a process. The pointer needs to point to
    /// valid UTF-8 encoded text with the given length.
    pub fn process_get_module_size(
        process: Process,
        name_ptr: *const u8,
        name_len: usize,
    ) -> Option<NonZeroU64>;
    /// Stores the file system path of a module in a process in the buffer
    /// given. The pointer to the module name needs to point to valid UTF-8
    /// encoded text with the given length. The path is a path that is
    /// accessible through the WASI file system, so a Windows path of
    /// `C:\foo\bar.exe` would be returned as `/mnt/c/foo/bar.exe`. Returns
    /// `false` if the buffer is too small. After this call, no matter whether
    /// it was successful or not, the `buf_len_ptr` will be set to the required
    /// buffer size. If `false` is returned and the `buf_len_ptr` got set to 0,
    /// the path or the module does not exist or it failed to get read. The path
    /// is guaranteed to be valid UTF-8 and is not nul-terminated.
    #[cfg(feature = "alloc")]
    pub fn process_get_module_path(
        process: Process,
        name_ptr: *const u8,
        name_len: usize,
        buf_ptr: *mut u8,
        buf_len_ptr: *mut usize,
    ) -> bool;
    /// Stores the file system path of the executable in the buffer given. The
    /// path is a path that is accessible through the WASI file system, so a
    /// Windows path of `C:\foo\bar.exe` would be returned as
    /// `/mnt/c/foo/bar.exe`. Returns `false` if the buffer is too small. After
    /// this call, no matter whether it was successful or not, the `buf_len_ptr`
    /// will be set to the required buffer size. If `false` is returned and the
    /// `buf_len_ptr` got set to 0, the path does not exist or failed to get
    /// read. The path is guaranteed to be valid UTF-8 and is not
    /// nul-terminated.
    #[cfg(feature = "alloc")]
    pub fn process_get_path(process: Process, buf_ptr: *mut u8, buf_len_ptr: *mut usize) -> bool;
    /// Gets the number of memory ranges in a given process.
    pub fn process_get_memory_range_count(process: Process) -> Option<NonZeroU64>;
    /// Gets the start address of a memory range by its index.
    pub fn process_get_memory_range_address(process: Process, idx: u64) -> Option<NonZeroAddress>;
    /// Gets the size of a memory range by its index.
    pub fn process_get_memory_range_size(process: Process, idx: u64) -> Option<NonZeroU64>;
    /// Gets the flags of a memory range by its index.
    #[cfg(feature = "flags")]
    pub fn process_get_memory_range_flags(process: Process, idx: u64) -> Option<NonZeroU64>;

    /// Sets the tick rate of the runtime. This influences the amount of
    /// times the `update` function is called per second.
    pub fn runtime_set_tick_rate(ticks_per_second: f64);
    /// Prints a log message for debugging purposes. The pointer needs to point
    /// to valid UTF-8 encoded text with the given length.
    pub fn runtime_print_message(text_ptr: *const u8, text_len: usize);
    /// Stores the name of the operating system that the runtime is running
    /// on in the buffer given. Returns `false` if the buffer is too small.
    /// After this call, no matter whether it was successful or not, the
    /// `buf_len_ptr` will be set to the required buffer size. The name is
    /// guaranteed to be valid UTF-8 and is not nul-terminated.
    /// Example values: `windows`, `linux`, `macos`
    pub fn runtime_get_os(buf_ptr: *mut u8, buf_len_ptr: *mut usize) -> bool;
    /// Stores the name of the architecture that the runtime is running on
    /// in the buffer given. Returns `false` if the buffer is too small.
    /// After this call, no matter whether it was successful or not, the
    /// `buf_len_ptr` will be set to the required buffer size. The name is
    /// guaranteed to be valid UTF-8 and is not nul-terminated.
    /// Example values: `x86`, `x86_64`, `arm`, `aarch64`
    pub fn runtime_get_arch(buf_ptr: *mut u8, buf_len_ptr: *mut usize) -> bool;

    /// Adds a new boolean setting that the user can modify. This will return
    /// either the specified default value or the value that the user has set.
    /// The key is used to store the setting and needs to be unique across all
    /// types of settings. The pointers need to point to valid UTF-8 encoded
    /// text with the respective given length.
    pub fn user_settings_add_bool(
        key_ptr: *const u8,
        key_len: usize,
        description_ptr: *const u8,
        description_len: usize,
        default_value: bool,
    ) -> bool;
    /// Adds a new title to the user settings. This is used to group settings
    /// together. The heading level determines the size of the title. The top
    /// level titles use a heading level of 0. The key needs to be unique across
    /// all types of settings. The pointers need to point to valid UTF-8 encoded
    /// text with the respective given length.
    pub fn user_settings_add_title(
        key_ptr: *const u8,
        key_len: usize,
        description_ptr: *const u8,
        description_len: usize,
        heading_level: u32,
    );
    /// Adds a new choice setting that the user can modify. This allows the user
    /// to choose between various options. The key is used to store the setting
    /// in the settings map and needs to be unique across all types of settings.
    /// The description is what's shown to the user. The key of the default
    /// option to show needs to be specified. The pointers need to point to
    /// valid UTF-8 encoded text with the respective given length.
    pub fn user_settings_add_choice(
        key_ptr: *const u8,
        key_len: usize,
        description_ptr: *const u8,
        description_len: usize,
        default_option_key_ptr: *const u8,
        default_option_key_len: usize,
    );
    /// Adds a new option to a choice setting. The key needs to match the key of
    /// the choice setting that it's supposed to be added to. The option key is
    /// used as the value to store when the user chooses this option. The
    /// description is what's shown to the user. The pointers need to point to
    /// valid UTF-8 encoded text with the respective given length. Returns
    /// `true` if the option is at this point in time chosen by the user.
    pub fn user_settings_add_choice_option(
        key_ptr: *const u8,
        key_len: usize,
        option_key_ptr: *const u8,
        option_key_len: usize,
        option_description_ptr: *const u8,
        option_description_len: usize,
    ) -> bool;
    /// Adds a new file select setting that the user can modify. This allows the
    /// user to choose a file from the file system. The key is used to store the
    /// path of the file in the settings map and needs to be unique across all
    /// types of settings. The description is what's shown to the user. The
    /// pointers need to point to valid UTF-8 encoded text with the respective
    /// given length. The path is a path that is accessible through the WASI
    /// file system, so a Windows path of `C:\foo\bar.exe` would be stored as
    /// `/mnt/c/foo/bar.exe`.
    pub fn user_settings_add_file_select(
        key_ptr: *const u8,
        key_len: usize,
        description_ptr: *const u8,
        description_len: usize,
    );
    /// Adds a filter to a file select setting. The key needs to match the key
    /// of the file select setting that it's supposed to be added to. The
    /// description is what's shown to the user for the specific filter. The
    /// description is optional. You may provide a null pointer if you don't
    /// want to specify a description. The pattern is a [glob
    /// pattern](https://en.wikipedia.org/wiki/Glob_(programming)) that is used
    /// to filter the files. The pattern generally only supports `*` wildcards,
    /// not `?` or brackets. This may however differ between frontends.
    /// Additionally `;` can't be used in Windows's native file dialog if it's
    /// part of the pattern. Multiple patterns may be specified by separating
    /// them with ASCII space characters. There are operating systems where glob
    /// patterns are not supported. A best effort lookup of the fitting MIME
    /// type may be used by a frontend on those operating systems instead. The
    /// pointers need to point to valid UTF-8 encoded text with the respective
    /// given length.
    pub fn user_settings_add_file_select_name_filter(
        key_ptr: *const u8,
        key_len: usize,
        description_ptr: *const u8,
        description_len: usize,
        pattern_ptr: *const u8,
        pattern_len: usize,
    );
    /// Adds a filter to a file select setting. The key needs to match the key
    /// of the file select setting that it's supposed to be added to. The MIME
    /// type is what's used to filter the files. Most operating systems do not
    /// support MIME types, but the frontends are encouraged to look up the file
    /// extensions that are associated with the MIME type and use those as a
    /// filter in those cases. You may also use wildcards as part of the MIME
    /// types such as `image/*`. The support likely also varies between
    /// frontends however. The pointers need to point to valid UTF-8 encoded
    /// text with the respective given length.
    pub fn user_settings_add_file_select_mime_filter(
        key_ptr: *const u8,
        key_len: usize,
        mime_type_ptr: *const u8,
        mime_type_len: usize,
    );
    /// Adds a tooltip to a setting based on its key. A tooltip is useful for
    /// explaining the purpose of a setting to the user. The pointers need to
    /// point to valid UTF-8 encoded text with the respective given length.
    pub fn user_settings_set_tooltip(
        key_ptr: *const u8,
        key_len: usize,
        tooltip_ptr: *const u8,
        tooltip_len: usize,
    );

    /// Creates a new settings map. You own the settings map and are responsible
    /// for freeing it.
    pub fn settings_map_new() -> SettingsMap;
    /// Frees a settings map.
    pub fn settings_map_free(map: SettingsMap);
    /// Loads a copy of the currently set global settings map. Any changes to it
    /// are only perceived if it's stored back. You own the settings map and are
    /// responsible for freeing it.
    pub fn settings_map_load() -> SettingsMap;
    /// Stores a copy of the settings map as the new global settings map. This
    /// will overwrite the previous global settings map. You still retain
    /// ownership of the map, which means you still need to free it. There's a
    /// chance that the settings map was changed in the meantime, so those
    /// changes could get lost. Prefer using `settings_map_store_if_unchanged`
    /// if you want to avoid that.
    pub fn settings_map_store(map: SettingsMap);
    /// Stores a copy of the new settings map as the new global settings map if
    /// the map has not changed in the meantime. This is done by comparing the
    /// old map. You still retain ownership of both maps, which means you still
    /// need to free them. Returns `true` if the map was stored successfully.
    /// Returns `false` if the map was changed in the meantime.
    pub fn settings_map_store_if_unchanged(old_map: SettingsMap, new_map: SettingsMap) -> bool;
    /// Copies a settings map. No changes inside the copy affect the original
    /// settings map. You own the new settings map and are responsible for
    /// freeing it.
    pub fn settings_map_copy(map: SettingsMap) -> SettingsMap;
    /// Inserts a copy of the setting value into the settings map based on the
    /// key. If the key already exists, it will be overwritten. You still retain
    /// ownership of the setting value, which means you still need to free it.
    /// The pointer needs to point to valid UTF-8 encoded text with the given
    /// length.
    pub fn settings_map_insert(
        map: SettingsMap,
        key_ptr: *const u8,
        key_len: usize,
        value: SettingValue,
    );
    /// Gets a copy of the setting value from the settings map based on the key.
    /// Returns `None` if the key does not exist. Any changes to it are only
    /// perceived if it's stored back. You own the setting value and are
    /// responsible for freeing it. The pointer needs to point to valid UTF-8
    /// encoded text with the given length.
    pub fn settings_map_get(
        map: SettingsMap,
        key_ptr: *const u8,
        key_len: usize,
    ) -> Option<SettingValue>;
    /// Gets the length of a settings map.
    pub fn settings_map_len(map: SettingsMap) -> u64;
    /// Gets the key of a setting value from the settings map based on the index
    /// by storing it into the buffer provided. Returns `false` if the buffer is
    /// too small. After this call, no matter whether it was successful or not,
    /// the `buf_len_ptr` will be set to the required buffer size. If `false` is
    /// returned and the `buf_len_ptr` got set to 0, the index is out of bounds.
    /// The key is guaranteed to be valid UTF-8 and is not nul-terminated.
    pub fn settings_map_get_key_by_index(
        map: SettingsMap,
        idx: u64,
        buf_ptr: *mut u8,
        buf_len_ptr: *mut usize,
    ) -> bool;
    /// Gets a copy of the setting value from the settings map based on the
    /// index. Returns `None` if the index is out of bounds. Any changes to it
    /// are only perceived if it's stored back. You own the setting value and
    /// are responsible for freeing it.
    pub fn settings_map_get_value_by_index(map: SettingsMap, idx: u64) -> Option<SettingValue>;

    /// Creates a new settings list. You own the settings list and are
    /// responsible for freeing it.
    pub fn settings_list_new() -> SettingsList;
    /// Frees a settings list.
    pub fn settings_list_free(list: SettingsList);
    /// Copies a settings list. No changes inside the copy affect the original
    /// settings list. You own the new settings list and are responsible for
    /// freeing it.
    pub fn settings_list_copy(list: SettingsList) -> SettingsList;
    /// Gets the length of a settings list.
    pub fn settings_list_len(list: SettingsList) -> u64;
    /// Gets a copy of the setting value from the settings list based on the
    /// index. Returns `None` if the index is out of bounds. Any changes to it
    /// are only perceived if it's stored back. You own the setting value and
    /// are responsible for freeing it.
    pub fn settings_list_get(list: SettingsList, idx: u64) -> Option<SettingValue>;
    /// Pushes a copy of the setting value to the end of the settings list. You
    /// still retain ownership of the setting value, which means you still need
    /// to free it.
    pub fn settings_list_push(list: SettingsList, value: SettingValue);
    /// Inserts a copy of the setting value into the settings list at the index
    /// given. Returns `false` if the index is out of bounds. No matter what
    /// happens, you still retain ownership of the setting value, which means
    /// you still need to free it.
    pub fn settings_list_insert(list: SettingsList, idx: u64, value: SettingValue) -> bool;

    /// Creates a new setting value from a settings map. The value is a copy of
    /// the settings map. Any changes to the original settings map afterwards
    /// are not going to be perceived by the setting value. You own the setting
    /// value and are responsible for freeing it. You also retain ownership of
    /// the settings map, which means you still need to free it.
    pub fn setting_value_new_map(value: SettingsMap) -> SettingValue;
    /// Creates a new setting value from a settings list. The value is a copy of
    /// the settings list. Any changes to the original settings list afterwards
    /// are not going to be perceived by the setting value. You own the setting
    /// value and are responsible for freeing it. You also retain ownership of
    /// the settings list, which means you still need to free it.
    pub fn setting_value_new_list(value: SettingsList) -> SettingValue;
    /// Creates a new boolean setting value. You own the setting value and are
    /// responsible for freeing it.
    pub fn setting_value_new_bool(value: bool) -> SettingValue;
    /// Creates a new 64-bit signed integer setting value. You own the setting
    /// value and are responsible for freeing it.
    pub fn setting_value_new_i64(value: i64) -> SettingValue;
    /// Creates a new 64-bit floating point setting value. You own the setting
    /// value and are responsible for freeing it.
    pub fn setting_value_new_f64(value: f64) -> SettingValue;
    /// Creates a new string setting value. The pointer needs to point to valid
    /// UTF-8 encoded text with the given length. You own the setting value and
    /// are responsible for freeing it.
    pub fn setting_value_new_string(value_ptr: *const u8, value_len: usize) -> SettingValue;
    /// Frees a setting value.
    pub fn setting_value_free(value: SettingValue);
    /// Copies a setting value. No changes inside the copy affect the original
    /// setting value. You own the new setting value and are responsible for
    /// freeing it.
    pub fn setting_value_copy(value: SettingValue) -> SettingValue;
    /// Gets the type of a setting value.
    pub fn setting_value_get_type(value: SettingValue) -> SettingValueType;
    /// Gets the value of a setting value as a settings map by storing it into
    /// the pointer provided. Returns `false` if the setting value is not a
    /// settings map. No value is stored into the pointer in that case. No
    /// matter what happens, you still retain ownership of the setting value,
    /// which means you still need to free it. You own the settings map and are
    /// responsible for freeing it.
    pub fn setting_value_get_map(value: SettingValue, value_ptr: *mut SettingsMap) -> bool;
    /// Gets the value of a setting value as a settings list by storing it into
    /// the pointer provided. Returns `false` if the setting value is not a
    /// settings list. No value is stored into the pointer in that case. No
    /// matter what happens, you still retain ownership of the setting value,
    /// which means you still need to free it. You own the settings list and are
    /// responsible for freeing it.
    pub fn setting_value_get_list(value: SettingValue, value_ptr: *mut SettingsList) -> bool;
    /// Gets the value of a boolean setting value by storing it into the pointer
    /// provided. Returns `false` if the setting value is not a boolean. No
    /// value is stored into the pointer in that case. No matter what happens,
    /// you still retain ownership of the setting value, which means you still
    /// need to free it.
    pub fn setting_value_get_bool(value: SettingValue, value_ptr: *mut bool) -> bool;
    /// Gets the value of a 64-bit signed integer setting value by storing it
    /// into the pointer provided. Returns `false` if the setting value is not a
    /// 64-bit signed integer. No value is stored into the pointer in that case.
    /// No matter what happens, you still retain ownership of the setting value,
    /// which means you still need to free it.
    pub fn setting_value_get_i64(value: SettingValue, value_ptr: *mut i64) -> bool;
    /// Gets the value of a 64-bit floating point setting value by storing it
    /// into the pointer provided. Returns `false` if the setting value is not a
    /// 64-bit floating point number. No value is stored into the pointer in
    /// that case. No matter what happens, you still retain ownership of the
    /// setting value, which means you still need to free it.
    pub fn setting_value_get_f64(value: SettingValue, value_ptr: *mut f64) -> bool;
    /// Gets the value of a string setting value by storing it into the buffer
    /// provided. Returns `false` if the buffer is too small or if the setting
    /// value is not a string. After this call, no matter whether it was
    /// successful or not, the `buf_len_ptr` will be set to the required buffer
    /// size. If `false` is returned and the `buf_len_ptr` got set to 0, the
    /// setting value is not a string. The string is guaranteed to be valid
    /// UTF-8 and is not nul-terminated. No matter what happens, you still
    /// retain ownership of the setting value, which means you still need to
    /// free it.
    pub fn setting_value_get_string(
        value: SettingValue,
        buf_ptr: *mut u8,
        buf_len_ptr: *mut usize,
    ) -> bool;
}