refactor: update time and cpal && upgrade to 1.88 and edition 2024 (#21)

* chore: update time and cpal + cargo update

* update to 1.88 and 2024

* use unsafe as needed

* update cbindgen

* ignore error in ReportSendErrorKind

* explicit dead_code attributes and update doc string

* jukebox: keep existing offset locator behavior while abiding by rust 2024 return-position impl rules

* minor doc comment adjustment

---------

Co-authored-by: Ryan McGrath <ryan@rymc.io>
Co-authored-by: Daryl Pinto <daryl.j.pinto@gmail.com>
This commit is contained in:
Nikhil Narayana
2025-07-19 16:10:57 -07:00
committed by GitHub
parent 3c02f240f8
commit 7ff0672fc4
27 changed files with 1052 additions and 645 deletions

1517
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ debug = true
panic = "abort"
[workspace.dependencies]
time = { version = "0.3.20", default-features = false, features = ["formatting", "parsing", "local-offset", "macros", "serde", "std"] }
time = { version = "0.3.41", default-features = false, features = ["formatting", "parsing", "local-offset", "macros", "serde", "std"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
serde_repr = { version = "0.1" }
@@ -35,16 +35,4 @@ tracing = { version = "0.1", default-features = false, features = ["std"] }
ureq = { version = "2.9.1", features = ["json"] }
[patch.crates-io]
# We need to patch this dependency to fix a bug in Windows where a crash can occur
# due to a lurking `assert` in cpal's wasapi device handling. This can be removed once
# the fix is merged upstream.
#
# See the following links for more info:
#
# - https://github.com/RustAudio/cpal/issues/796
# - https://github.com/project-slippi/cpal/commit/b0058fc99e324e919cba099077f43db90ddada94
#
# We have also added some extra logging ourselves to try to track down the source of the issue.
#
cpal = { git = "https://github.com/project-slippi/cpal.git", ref="1ec6b46495d702b067e5574cbda0cae2fc9dbae3" }
cpal = { version = "0.16.0" }

View File

@@ -6,7 +6,7 @@ authors = [
"Slippi Team",
"Ryan McGrath <ryan@rymc.io>"
]
edition = "2021"
edition = "2024"
publish = false
[features]

View File

@@ -3,7 +3,7 @@
//! Typically you can just import the `Dolphin` struct and use that as a namespace for accessing
//! all functionality at once.
use std::ffi::{c_char, CString};
use std::ffi::{CString, c_char};
mod logger;
pub use logger::Log;

View File

@@ -9,7 +9,7 @@ use time::OffsetDateTime;
use tracing::{Level, Metadata};
use tracing_subscriber::Layer;
use super::{ForeignLoggerFn, Log, LOG_CONTAINERS};
use super::{ForeignLoggerFn, LOG_CONTAINERS, Log};
/// Corresponds to Dolphin's `LogTypes::LOG_LEVELS::LNOTICE` value.
#[allow(dead_code)]

View File

@@ -7,14 +7,14 @@
//!
//! Ultimately this should mean no log fragmentation or confusion.
use std::ffi::{c_char, c_int, CStr};
use std::ffi::{CStr, c_char, c_int};
use std::sync::{Arc, Once, OnceLock, RwLock};
use tracing::Level;
use tracing_subscriber::prelude::*;
mod layer;
use layer::{convert_dolphin_log_level_to_tracing_level, DolphinLoggerLayer};
use layer::{DolphinLoggerLayer, convert_dolphin_log_level_to_tracing_level};
/// A type that mirrors a function over on the C++ side; because the library exists as
/// a dylib, it can't depend on any functions from the host application - but we _can_
@@ -86,7 +86,9 @@ pub fn init(logger_fn: ForeignLoggerFn) {
// know if something else, somehow, registered before us.
LOGGER.call_once(|| {
// We do this so that full backtrace's are emitted on any crashes.
std::env::set_var("RUST_BACKTRACE", "full");
unsafe {
std::env::set_var("RUST_BACKTRACE", "full");
}
tracing_subscriber::registry().with(DolphinLoggerLayer::new(logger_fn)).init();
});

View File

@@ -6,7 +6,7 @@ authors = [
"Slippi Team",
"Ryan McGrath <ryan@rymc.io>"
]
edition = "2021"
edition = "2024"
publish = false
[features]

View File

@@ -7,14 +7,14 @@ authors = [
"Ryan McGrath <ryan@rymc.io>"
]
repository = ""
edition = "2021"
edition = "2024"
publish = false
[lib]
crate-type = ["cdylib"]
[build-dependencies]
cbindgen = "0.24.3"
cbindgen = "0.29.0"
[features]
default = ["ishiiruka"]

View File

@@ -377,5 +377,5 @@ char *slprs_user_direct_codes_get_code_at_index(uintptr_t exi_device_instance_pt
void slprs_user_direct_codes_free_code(char *code);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@@ -43,7 +43,7 @@ pub struct SlippiRustEXIConfig {
/// down (at whatever point) via the corresponding `slprs_exi_device_destroy` function.
///
/// The returned pointer from this should *not* be used after calling `slprs_exi_device_destroy`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_create(config: SlippiRustEXIConfig) -> usize {
dolphin_integrations::ffi::osd::set_global_hook(config.osd_add_msg_fn);
@@ -73,7 +73,7 @@ pub extern "C" fn slprs_exi_device_create(config: SlippiRustEXIConfig) -> usize
/// The C++ (Dolphin) side of things should call this to notify the Rust side that it
/// can safely shut down and clean up.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_destroy(exi_device_instance_ptr: usize) {
tracing::warn!(
target: Log::SlippiOnline,
@@ -94,7 +94,7 @@ pub extern "C" fn slprs_exi_device_destroy(exi_device_instance_ptr: usize) {
/// the Dolphin side, corresponding to:
///
/// `virtual void DMAWrite(u32 _uAddr, u32 _uSize);`
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_dma_write(exi_device_instance_ptr: usize, address: *const u8, size: *const u8) {
// Coerce the instance back from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` pointer is only owned
@@ -111,7 +111,7 @@ pub extern "C" fn slprs_exi_device_dma_write(exi_device_instance_ptr: usize, add
/// the Dolphin side, corresponding to:
///
/// `virtual void DMARead(u32 _uAddr, u32 _uSize);`
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_dma_read(exi_device_instance_ptr: usize, address: *const u8, size: *const u8) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` pointer is only owned
@@ -129,7 +129,7 @@ pub extern "C" fn slprs_exi_device_dma_read(exi_device_instance_ptr: usize, addr
/// will then add it to the processing pipeline.
///
/// The reporter will manage the actual... reporting.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_log_game_report(instance_ptr: usize, game_report_instance_ptr: usize) {
// Coerce the instances from the pointers. This is theoretically safe since we control
// the C++ side and can guarantee that the pointers are only owned
@@ -148,7 +148,7 @@ pub extern "C" fn slprs_exi_device_log_game_report(instance_ptr: usize, game_rep
}
/// Calls through to `SlippiGameReporter::start_new_session`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_start_new_reporter_session(instance_ptr: usize) {
// Coerce the instances from the pointers. This is theoretically safe since we control
// the C++ side and can guarantee that the pointers are only owned
@@ -163,7 +163,7 @@ pub extern "C" fn slprs_exi_device_start_new_reporter_session(instance_ptr: usiz
/// Calls through to the `SlippiGameReporter` on the EXI device to report a
/// match completion event.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_report_match_completion(instance_ptr: usize, match_id: *const c_char, end_mode: u8) {
// Coerce the instances from the pointers. This is theoretically safe since we control
// the C++ side and can guarantee that the pointers are only owned
@@ -181,7 +181,7 @@ pub extern "C" fn slprs_exi_device_report_match_completion(instance_ptr: usize,
/// Calls through to the `SlippiGameReporter` on the EXI device to report a
/// match abandon event.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_report_match_abandonment(instance_ptr: usize, match_id: *const c_char) {
// Coerce the instances from the pointers. This is theoretically safe since we control
// the C++ side and can guarantee that the pointers are only owned
@@ -198,7 +198,7 @@ pub extern "C" fn slprs_exi_device_report_match_abandonment(instance_ptr: usize,
}
/// Calls through to `SlippiGameReporter::push_replay_data`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_reporter_push_replay_data(instance_ptr: usize, data: *const u8, length: u32) {
// Convert our pointer to a Rust slice so that the game reporter
// doesn't need to deal with anything C-ish.
@@ -218,7 +218,7 @@ pub extern "C" fn slprs_exi_device_reporter_push_replay_data(instance_ptr: usize
/// Configures the Jukebox process. This needs to be called after the EXI device is created
/// in order for certain pieces of Dolphin to be properly initalized; this may change down
/// the road though and is not set in stone.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_exi_device_configure_jukebox(
exi_device_instance_ptr: usize,
is_enabled: bool,

View File

@@ -25,7 +25,7 @@ pub enum SlippiMatchmakingOnlinePlayMode {
/// Creates a new Player Report and leaks it, returning the pointer.
///
/// This should be passed on to a GameReport for processing.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_player_report_create(
uid: *const c_char,
slot_type: u8,
@@ -59,7 +59,7 @@ pub extern "C" fn slprs_player_report_create(
///
/// This is expected to ultimately be passed to the game reporter, which will handle
/// destruction and cleanup.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_game_report_create(
uid: *const c_char,
play_key: *const c_char,
@@ -109,7 +109,7 @@ pub extern "C" fn slprs_game_report_create(
/// Takes ownership of the `PlayerReport` at the specified pointer, adding it to the
/// `GameReport` at the corresponding pointer.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_game_report_add_player_report(instance_ptr: usize, player_report_instance_ptr: usize) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `game_report_instance_ptr` is only owned

View File

@@ -2,7 +2,7 @@ use slippi_exi_device::SlippiEXIDevice;
use slippi_jukebox::VolumeControl;
/// Calls through to `Jukebox::start_song`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_jukebox_start_song(exi_device_instance_ptr: usize, hps_offset: u64, hps_length: usize) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` is only owned
@@ -18,7 +18,7 @@ pub extern "C" fn slprs_jukebox_start_song(exi_device_instance_ptr: usize, hps_o
}
/// Calls through to `Jukebox::stop_music`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_jukebox_stop_music(exi_device_instance_ptr: usize) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` is only owned
@@ -34,7 +34,7 @@ pub extern "C" fn slprs_jukebox_stop_music(exi_device_instance_ptr: usize) {
}
/// Calls through to `Jukebox::set_volume` with the Melee volume control.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_jukebox_set_melee_music_volume(exi_device_instance_ptr: usize, volume: u8) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` is only owned
@@ -50,7 +50,7 @@ pub extern "C" fn slprs_jukebox_set_melee_music_volume(exi_device_instance_ptr:
}
/// Calls through to `Jukebox::set_volume` with the DolphinSystem volume control.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_jukebox_set_dolphin_system_volume(exi_device_instance_ptr: usize, volume: u8) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` is only owned
@@ -66,7 +66,7 @@ pub extern "C" fn slprs_jukebox_set_dolphin_system_volume(exi_device_instance_pt
}
/// Calls through to `Jukebox::set_volume` with the DolphinMusic volume control.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_jukebox_set_dolphin_music_volume(exi_device_instance_ptr: usize, volume: u8) {
// Coerce the instance from the pointer. This is theoretically safe since we control
// the C++ side and can guarantee that the `exi_device_instance_ptr` is only owned

View File

@@ -5,7 +5,7 @@
//! This library auto-generates C headers on build, and Slippi Dolphin is pre-configured
//! to locate these headers and link the entire dylib.
use std::ffi::{c_char, CStr};
use std::ffi::{CStr, c_char};
use dolphin_integrations::Log;

View File

@@ -11,7 +11,7 @@ use std::ffi::{c_char, c_int};
/// ```
/// void Log(level, log_type, msg);
/// ```
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_logging_init(logger_fn: unsafe extern "C" fn(c_int, c_int, *const c_char)) {
dolphin_integrations::ffi::logger::init(logger_fn);
}
@@ -19,7 +19,7 @@ pub extern "C" fn slprs_logging_init(logger_fn: unsafe extern "C" fn(c_int, c_in
/// Registers a log container, which mirrors a Dolphin `LogContainer` (`RustLogContainer`).
///
/// See `dolphin_logger::register_container` for more information.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_logging_register_container(
kind: *const c_char,
log_type: c_int,
@@ -32,7 +32,7 @@ pub extern "C" fn slprs_logging_register_container(
/// Updates the configuration for a registered logging container.
///
/// For more information, see `dolphin_logger::update_container`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_logging_update_container(kind: *const c_char, enabled: bool, level: c_int) {
dolphin_integrations::ffi::logger::update_container(kind, enabled, level);
}
@@ -40,7 +40,7 @@ pub extern "C" fn slprs_logging_update_container(kind: *const c_char, enabled: b
/// Updates the configuration for registered logging container on mainline
///
/// For more information, see `dolphin_logger::update_container`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_mainline_logging_update_log_level(level: c_int) {
dolphin_integrations::ffi::logger::mainline_update_log_level(level);
}

View File

@@ -1,4 +1,4 @@
use std::ffi::{c_char, c_int, CString};
use std::ffi::{CString, c_char, c_int};
use slippi_exi_device::SlippiEXIDevice;
@@ -6,14 +6,14 @@ use crate::{c_str_to_string, with, with_returning};
/// Instructs the `UserManager` on the EXI Device at the provided pointer to attempt
/// authentication. This runs synchronously on whatever thread it's called on.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_attempt_login(exi_device_instance_ptr: usize) -> bool {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, |device| device.user_manager.attempt_login())
}
/// Instructs the `UserManager` on the EXI Device at the provided pointer to try to
/// open the login page in a system-provided browser view.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_open_login_page(exi_device_instance_ptr: usize) {
with::<SlippiEXIDevice, _>(exi_device_instance_ptr, |device| {
device.user_manager.open_login_page();
@@ -22,7 +22,7 @@ pub extern "C" fn slprs_user_open_login_page(exi_device_instance_ptr: usize) {
/// Instructs the `UserManager` on the EXI Device at the provided pointer to attempt
/// to initiate the older update flow.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_update_app(exi_device_instance_ptr: usize) -> bool {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, |device| device.user_manager.update_app())
}
@@ -30,7 +30,7 @@ pub extern "C" fn slprs_user_update_app(exi_device_instance_ptr: usize) -> bool
/// Instructs the `UserManager` on the EXI Device at the provided pointer to start watching
/// for the presence of a `user.json` file. The `UserManager` should have the requisite path
/// already from EXI device instantiation.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_listen_for_login(exi_device_instance_ptr: usize) {
with::<SlippiEXIDevice, _>(exi_device_instance_ptr, |device| {
device.user_manager.watch_for_login();
@@ -39,7 +39,7 @@ pub extern "C" fn slprs_user_listen_for_login(exi_device_instance_ptr: usize) {
/// Instructs the `UserManager` on the EXI Device at the provided pointer to sign the user out.
/// This will delete the `user.json` file from the underlying filesystem.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_logout(exi_device_instance_ptr: usize) {
with::<SlippiEXIDevice, _>(exi_device_instance_ptr, |device| {
device.user_manager.logout();
@@ -48,7 +48,7 @@ pub extern "C" fn slprs_user_logout(exi_device_instance_ptr: usize) {
/// Hooks through the `UserManager` on the EXI Device at the provided pointer to overwrite the
/// latest version field on the current user.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_overwrite_latest_version(exi_device_instance_ptr: usize, version: *const c_char) {
let version = c_str_to_string(version, "slprs_user_overwrite_latest_version", "version");
@@ -59,7 +59,7 @@ pub extern "C" fn slprs_user_overwrite_latest_version(exi_device_instance_ptr: u
/// Hooks through the `UserManager` on the EXI Device at the provided pointer to determine
/// authentication status.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_get_is_logged_in(exi_device_instance_ptr: usize) -> bool {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, |device| device.user_manager.is_logged_in())
}
@@ -84,7 +84,7 @@ pub struct RustUserInfo {
/// This involves slightly more allocations than ideal, so this shouldn't be called in a hot path.
/// Over time this issue will not matter as once Matchmaking is moved to Rust we can share things
/// quite easily.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_get_info(exi_device_instance_ptr: usize) -> *mut RustUserInfo {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, |device| {
let user_info = device.user_manager.get(|user| {
@@ -124,7 +124,7 @@ pub extern "C" fn slprs_user_get_info(exi_device_instance_ptr: usize) -> *mut Ru
/// When the C/C++ side grabs `UserInfo`, it needs to ensure that it's passed back to Rust
/// to ensure that the memory layout matches - do _not_ call `free` on `UserInfo`, pass it here
/// instead.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_free_info(ptr: *mut RustUserInfo) {
if ptr.is_null() {
// Log here~?
@@ -188,7 +188,7 @@ impl RustChatMessages {
/// Returns a C-compatible struct containing the chat message options for the current user.
///
/// The return value of this _must_ be passed back to `slprs_user_free_messages` to free memory.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_get_messages(exi_device_instance_ptr: usize) -> *mut RustChatMessages {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, |device| {
let messages = device.user_manager.get(|user| {
@@ -205,7 +205,7 @@ pub extern "C" fn slprs_user_get_messages(exi_device_instance_ptr: usize) -> *mu
/// Returns a C-compatible struct containing the default chat message options.
///
/// The return value of this _must_ be passed back to `slprs_user_free_messages` to free memory.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_get_default_messages(exi_device_instance_ptr: usize) -> *mut RustChatMessages {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, |_device| {
let messages = Box::new(RustChatMessages::from(&slippi_user::DEFAULT_CHAT_MESSAGES));
@@ -215,7 +215,7 @@ pub extern "C" fn slprs_user_get_default_messages(exi_device_instance_ptr: usize
/// Takes back ownership of a `RustChatMessages` instance and frees the underlying data
/// by converting it into the proper Rust types.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_free_messages(ptr: *mut RustChatMessages) {
if ptr.is_null() {
// Log here~?
@@ -244,7 +244,7 @@ pub enum DirectCodeKind {
}
/// Passes along a direct code to add or update.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_direct_codes_add_or_update(
exi_device_instance_ptr: usize,
kind: DirectCodeKind,
@@ -264,7 +264,7 @@ pub extern "C" fn slprs_user_direct_codes_add_or_update(
}
/// Gets the length of the current direct codes stack for the given `kind`.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_direct_codes_get_length(exi_device_instance_ptr: usize, kind: DirectCodeKind) -> u32 {
with_returning::<SlippiEXIDevice, _, _>(exi_device_instance_ptr, move |device| match kind {
DirectCodeKind::DirectCodes => device.user_manager.direct_codes.len() as u32,
@@ -278,7 +278,7 @@ pub extern "C" fn slprs_user_direct_codes_get_length(exi_device_instance_ptr: us
/// this will go away over time. Just be aware it's doing more allocations than is perhaps
/// ideal... but this area of code isn't performance sensitive anyway as it's not core
/// gameplay.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_direct_codes_get_code_at_index(
exi_device_instance_ptr: usize,
kind: DirectCodeKind,
@@ -296,7 +296,7 @@ pub extern "C" fn slprs_user_direct_codes_get_code_at_index(
/// As the allocator on the C++ could be different, we need to provide a `free` method
/// that the C++ side will call when it's handled everything it needs to do.
#[no_mangle]
#[unsafe(no_mangle)]
pub extern "C" fn slprs_user_direct_codes_free_code(code: *mut c_char) {
unsafe {
if !code.is_null() {

View File

@@ -3,7 +3,7 @@ name = "slippi-game-reporter"
description = "Implements the game reporter service."
authors = ["Slippi Team", "Ryan McGrath <ryan@rymc.io>"]
version = "0.1.0"
edition = "2021"
edition = "2024"
publish = false
[features]

View File

@@ -2,9 +2,9 @@
//! not to rewrite the universe.
use std::ops::Deref;
use std::sync::mpsc::{self, Sender};
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::mpsc::{self, Sender};
use std::thread;
use dolphin_integrations::Log;

View File

@@ -7,9 +7,9 @@ use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use flate2::write::GzEncoder;
use flate2::Compression;
use serde_json::{json, Value};
use flate2::write::GzEncoder;
use serde_json::{Value, json};
use dolphin_integrations::{Color, Dolphin, Duration as OSDDuration, Log};
use slippi_gg_api::APIClient;
@@ -263,11 +263,18 @@ fn process_reports(queue: &GameReporterQueue, event: ProcessingEvent) {
}
/// The true inner error, minus any metadata.
/// the compiler thinks the fields are unused, but they're not.
/// debug impls will render them over the Dolphin logging interface
/// and the compiler just doesn't see that.
#[derive(Debug)]
enum ReportSendErrorKind {
#[allow(dead_code)]
Net(slippi_gg_api::Error),
#[allow(dead_code)]
JSON(serde_json::Error),
#[allow(dead_code)]
GraphQL(String),
#[allow(dead_code)]
NotSuccessful(String),
}

View File

@@ -6,7 +6,7 @@ authors = [
"Slippi Team",
"Daryl Pinto <daryl.j.pinto@gmail.com>"
]
edition = "2021"
edition = "2024"
publish = false
exclude = ["/test-data"]

View File

@@ -49,7 +49,12 @@ pub(crate) fn get_iso_kind(iso: &mut File) -> Result<IsoKind> {
/// let get_true_offset = create_offset_locator_fn(&mut iso)?;
/// let offset = get_true_offset(0x424);
/// ```
pub(crate) fn create_offset_locator_fn(iso: &mut File) -> Result<impl Fn(u64) -> Option<u64>> {
///
/// Technical note:
/// The returned function does not capture any references which is why it is
/// marked as 'static. This must be explicit in the 2024 edition:
/// https://blog.rust-lang.org/2024/09/05/impl-trait-capture-rules/
pub(crate) fn create_offset_locator_fn(iso: &mut File) -> Result<impl Fn(u64) -> Option<u64> + 'static> {
// Get the ciso header (block size and block map) of the provided file.
// If the file is not a ciso, this will be `None`
let ciso_header = ciso::get_ciso_header(iso)?;

View File

@@ -1,7 +1,7 @@
use std::convert::TryInto;
use std::fmt::Debug;
use std::fs::File;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::mpsc::{Receiver, Sender, channel};
use dolphin_integrations::{Color, Dolphin, Duration as OSDDuration, Log};
use hps_decode::Hps;
@@ -10,11 +10,11 @@ use rodio::{OutputStream, Sink};
use crate::Message::*;
mod errors;
pub use errors::JukeboxError;
use JukeboxError::*;
pub use errors::JukeboxError;
mod disc;
use disc::{get_iso_kind, IsoKind};
use disc::{IsoKind, get_iso_kind};
mod utils;
use utils::copy_bytes_from_file;

View File

@@ -1,4 +1,4 @@
[toolchain]
channel = "1.70.0"
channel = "1.88.0"
components = ["rustfmt", "rustc-dev"]
profile = "minimal"

View File

@@ -7,7 +7,7 @@ authors = [
"Ryan McGrath <ryan@rymc.io>"
]
repository = ""
edition = "2021"
edition = "2024"
publish = false
[dependencies]

View File

@@ -6,7 +6,7 @@ authors = [
"Ryan McGrath <ryan@rymc.io>"
]
version = "0.1.0"
edition = "2021"
edition = "2024"
publish = false
[features]

View File

@@ -8,8 +8,8 @@
//! unix timestamp handling code.
use serde::{Deserialize, Serialize};
use time::macros::format_description;
use time::OffsetDateTime;
use time::macros::format_description;
/// Serializes a timestamp as a unix timestamp (`i64`).
pub fn serialize<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>

View File

@@ -132,7 +132,7 @@ impl DirectCodes {
let mut codes = self.codes.lock().expect("Unable to lock codes for autocomplete");
let mut found = false;
for mut entry in codes.iter_mut() {
for entry in codes.iter_mut() {
if entry.connect_code == code {
found = true;
entry.last_played = last_played;

View File

@@ -6,7 +6,7 @@ use std::time::Duration;
use slippi_gg_api::APIClient;
use super::{attempt_login, UserInfo};
use super::{UserInfo, attempt_login};
/// This type manages access to user information, as well as any background thread watching
/// for `user.json` file existence.
@@ -50,16 +50,18 @@ impl UserInfoWatcher {
let watcher_thread = thread::Builder::new()
.name("SlippiUserJSONWatcherThread".into())
.spawn(move || loop {
if !should_watch.load(Ordering::Relaxed) {
return;
}
.spawn(move || {
loop {
if !should_watch.load(Ordering::Relaxed) {
return;
}
if attempt_login(&api_client, &user, &user_json_path, &slippi_semver) {
return;
}
if attempt_login(&api_client, &user, &user_json_path, &slippi_semver) {
return;
}
thread::sleep(Duration::from_millis(500));
thread::sleep(Duration::from_millis(500));
}
})
.expect("Failed to spawn SlippiUserJSONWatcherThread");