1use std::fmt;
2
3#[derive(Debug)]
4pub enum ServerError {
5 AuthFailed(String),
6 AuthTimeout,
7 RoomNotFound(String),
8 RoomFull(String),
9 IncorrectPassword,
10 NotInRoom,
11 NotHost,
12 PlayersNotReady,
13 DeckNotSelected,
14 AlreadyInRoom(String),
15 GameAlreadyStarted,
16 GameNotInProgress,
17 FormatNotChosen,
18 InvalidDraftConfig(String),
19 InvalidResumeToken,
20 DuplicateUsername(String),
21 PlayerNotFound(String),
22 PlayerInGame(String),
23 InvalidChatMessage(String),
24 ChatRateLimited,
25 AccountRequired,
26 WebSocket(Box<tokio_tungstenite::tungstenite::Error>),
27 Serde(serde_json::Error),
28}
29
30impl fmt::Display for ServerError {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 Self::AuthFailed(msg) => write!(f, "Authentication failed: {msg}"),
34 Self::AuthTimeout => write!(f, "Authentication timed out"),
35 Self::RoomNotFound(id) => write!(f, "Room not found: {id}"),
36 Self::RoomFull(id) => write!(f, "Room is full: {id}"),
37 Self::IncorrectPassword => write!(f, "Incorrect room password"),
38 Self::NotInRoom => write!(f, "You are not in a room"),
39 Self::NotHost => write!(f, "Only the host can do that"),
40 Self::PlayersNotReady => write!(f, "Not all players are ready"),
41 Self::DeckNotSelected => write!(f, "You must select a deck before getting ready"),
42 Self::GameAlreadyStarted => write!(f, "Game has already started"),
43 Self::GameNotInProgress => write!(f, "No game is in progress"),
44 Self::FormatNotChosen => write!(f, "A format must be chosen before starting"),
45 Self::InvalidDraftConfig(msg) => write!(f, "Invalid draft config: {msg}"),
46 Self::InvalidResumeToken => write!(f, "Invalid resume token"),
47 Self::AlreadyInRoom(id) => write!(f, "Already in room: {id}"),
48 Self::DuplicateUsername(name) => write!(f, "Username already taken: {name}"),
49 Self::PlayerNotFound(name) => write!(f, "Player not found: {name}"),
50 Self::PlayerInGame(name) => write!(f, "Player is in a game: {name}"),
51 Self::InvalidChatMessage(msg) => write!(f, "Invalid chat message: {msg}"),
52 Self::ChatRateLimited => write!(f, "You are sending messages too quickly"),
53 Self::AccountRequired => write!(f, "Sign in to chat in General"),
54 Self::WebSocket(e) => write!(f, "WebSocket error: {e}"),
55 Self::Serde(e) => write!(f, "Serialization error: {e}"),
56 }
57 }
58}
59
60impl std::error::Error for ServerError {}
61
62impl ServerError {
63 pub fn code(&self) -> &'static str {
64 match self {
65 Self::AuthFailed(_) => "auth_failed",
66 Self::AuthTimeout => "auth_timeout",
67 Self::RoomNotFound(_) => "room_not_found",
68 Self::RoomFull(_) => "room_full",
69 Self::IncorrectPassword => "incorrect_password",
70 Self::NotInRoom => "not_in_room",
71 Self::NotHost => "not_host",
72 Self::PlayersNotReady => "players_not_ready",
73 Self::DeckNotSelected => "deck_not_selected",
74 Self::GameAlreadyStarted => "game_already_started",
75 Self::GameNotInProgress => "game_not_in_progress",
76 Self::FormatNotChosen => "format_not_chosen",
77 Self::InvalidDraftConfig(_) => "invalid_draft_config",
78 Self::InvalidResumeToken => "invalid_resume_token",
79 Self::AlreadyInRoom(_) => "already_in_room",
80 Self::DuplicateUsername(_) => "duplicate_username",
81 Self::PlayerNotFound(_) => "player_not_found",
82 Self::PlayerInGame(_) => "player_in_game",
83 Self::InvalidChatMessage(_) => "invalid_chat_message",
84 Self::ChatRateLimited => "chat_rate_limited",
85 Self::AccountRequired => "account_required",
86 Self::WebSocket(_) => "websocket_error",
87 Self::Serde(_) => "parse_error",
88 }
89 }
90}
91
92impl From<tokio_tungstenite::tungstenite::Error> for ServerError {
93 fn from(e: tokio_tungstenite::tungstenite::Error) -> Self {
94 Self::WebSocket(Box::new(e))
95 }
96}
97
98impl From<serde_json::Error> for ServerError {
99 fn from(e: serde_json::Error) -> Self {
100 Self::Serde(e)
101 }
102}