Files
soulseek-rs-modded/soulseek-rs-lib/src/error.rs
T
michel 2722552e35 refactor: replace lock unwraps with poison-aware helpers
Add SoulseekRs::LockPoisoned variant and a small RwLockExt/MutexExt
helper module exposing read_safe/write_safe/lock_safe that map
PoisonError to that variant. Walk every non-test lock acquisition
across client, peer/server actors, peer registry, listener and the
thread pool: propagate via ? where the function returns Result, log
and degrade to a sensible default (return early, false, None, empty)
where it does not. Client::connect now returns Result so the CLI can
surface the failure instead of panicking.
2026-04-26 12:32:46 +02:00

80 lines
2.4 KiB
Rust

use std::{error::Error, fmt};
/// Custom error type for the Soulseek download library
#[derive(Debug)]
pub enum SoulseekRs {
NetworkError(std::io::Error),
/// Authentication failed during login
AuthenticationFailed,
/// Error parsing messages or data
ParseError(String),
/// Operation timed out
Timeout,
/// Connection was closed unexpectedly
ConnectionClosed,
/// Invalid message format or content
InvalidMessage(String),
/// Server not connected
NotConnected,
/// Compression/decompression error
CompressionError(String),
/// A lock was poisoned by a panic in another thread
LockPoisoned,
}
impl fmt::Display for SoulseekRs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SoulseekRs::NetworkError(err) => {
write!(f, "Network error: {}", err)
}
SoulseekRs::AuthenticationFailed => {
write!(f, "Authentication failed")
}
SoulseekRs::ParseError(msg) => write!(f, "Parse error: {}", msg),
SoulseekRs::Timeout => write!(f, "Operation timed out"),
SoulseekRs::ConnectionClosed => write!(f, "Connection closed"),
SoulseekRs::InvalidMessage(msg) => {
write!(f, "Invalid message: {}", msg)
}
SoulseekRs::NotConnected => write!(f, "Not connected to server"),
SoulseekRs::CompressionError(msg) => {
write!(f, "Compression error: {}", msg)
}
SoulseekRs::LockPoisoned => {
write!(f, "Lock poisoned by panicking thread")
}
}
}
}
impl Error for SoulseekRs {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
SoulseekRs::NetworkError(err) => Some(err),
_ => None,
}
}
}
impl From<std::io::Error> for SoulseekRs {
fn from(err: std::io::Error) -> Self {
SoulseekRs::NetworkError(err)
}
}
impl From<std::num::ParseIntError> for SoulseekRs {
fn from(err: std::num::ParseIntError) -> Self {
SoulseekRs::ParseError(format!("Integer parse error: {}", err))
}
}
impl From<String> for SoulseekRs {
fn from(err: String) -> Self {
SoulseekRs::CompressionError(err)
}
}
/// Result type alias for the Soulseek library
pub type Result<T> = std::result::Result<T, SoulseekRs>;