Skip to main content

server/domain/players/
player.rs

1use serde::{Deserialize, Serialize};
2
3/// Represents a player in the game.
4///
5/// This is a simple wrapper around a `usize` index to distinguish players
6/// in a type-safe manner. Only two players are supported in this implementation
7/// of the game.
8#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
9#[repr(transparent)]
10#[serde(transparent)]
11pub struct Player(usize);
12
13/// The first player (index 0).
14pub const PLAYER0: Player = Player(0);
15
16/// The second player (index 1).
17pub const PLAYER1: Player = Player(1);
18
19/// An array of all players in the game.
20///
21/// This array is useful for iterating over players.
22pub const PLAYERS: [Player; 2] = [PLAYER0, PLAYER1];
23
24impl Player {
25    /// Returns the opponent of this player.
26    pub const fn opponent(&self) -> Self {
27        Self(1 - self.0)
28    }
29}
30
31impl<T> std::ops::Index<Player> for [T] {
32    type Output = T;
33
34    fn index(&self, index: Player) -> &Self::Output {
35        &self[index.0]
36    }
37}
38
39impl<T> std::ops::Index<&Player> for [T] {
40    type Output = T;
41
42    fn index(&self, index: &Player) -> &Self::Output {
43        &self[index.0]
44    }
45}
46
47impl<T> std::ops::Index<Player> for Vec<T> {
48    type Output = T;
49
50    fn index(&self, index: Player) -> &Self::Output {
51        &self[index.0]
52    }
53}
54
55impl<T> std::ops::IndexMut<Player> for [T] {
56    fn index_mut(&mut self, index: Player) -> &mut Self::Output {
57        &mut self[index.0]
58    }
59}
60
61impl<T> std::ops::IndexMut<&Player> for [T] {
62    fn index_mut(&mut self, index: &Player) -> &mut Self::Output {
63        &mut self[index.0]
64    }
65}
66
67#[cfg(test)]
68impl From<usize> for Player {
69    fn from(value: usize) -> Self {
70        Self(value)
71    }
72}
73
74impl std::fmt::Display for Player {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "Player({})", self.0)
77    }
78}