riichi_elements/
player.rs1use core::fmt::{Debug, Display, Formatter};
4use core::ops::{Add, Sub};
5use derive_more::{From, Into};
6
7#[derive(Copy, Clone, Default, Eq, PartialEq, Hash, From, Into)]
20pub struct Player(u8);
21
22pub const P0: Player = Player(0);
23pub const P1: Player = Player(1);
24pub const P2: Player = Player(2);
25pub const P3: Player = Player(3);
26pub const ALL_PLAYERS: [Player; 4] = [P0, P1, P2, P3];
27
28impl Player {
29 pub const fn new(x: u8) -> Self { Player(x & 3) }
30
31 pub const fn add(self, other: Player) -> Player {
32 Player(self.0.wrapping_add(other.0) & 3)
33 }
34
35 pub const fn add_u8(self, other: u8) -> Player {
36 Player(self.0.wrapping_add(other) & 3)
37 }
38
39 pub const fn sub(self, other: Player) -> Player {
40 Player(self.0.wrapping_sub(other.0) & 3)
41 }
42
43 pub const fn sub_u8(self, other: u8) -> Player {
44 Player(self.0.wrapping_sub(other) & 3)
45 }
46
47 pub const fn to_u8(self) -> u8 { self.0 }
48 pub const fn to_usize(self) -> usize { self.0 as usize }
49
50 pub const fn succ(self) -> Self { self.add(P1) }
53
54 pub const fn oppo(self) -> Self { self.add(P2) }
57
58 pub const fn pred(self) -> Self { self.add(P3) }
61}
62
63impl From<usize> for Player {
64 fn from(x: usize) -> Self { Self::new(x as u8) }
65}
66
67impl Into<usize> for Player {
68 fn into(self) -> usize { self.0 as usize }
69}
70
71impl Add for Player {
72 type Output = Player;
73 fn add(self, rhs: Self) -> Self::Output { self.add(rhs) }
74}
75
76impl Add<u8> for Player {
77 type Output = Player;
78 fn add(self, rhs: u8) -> Self::Output { self.add_u8(rhs) }
79}
80
81impl Sub for Player {
82 type Output = Player;
83 fn sub(self, rhs: Self) -> Self::Output { self.sub(rhs) }
84}
85
86impl Sub<u8> for Player {
87 type Output = Player;
88 fn sub(self, rhs: u8) -> Self::Output { self.sub_u8(rhs) }
89}
90
91impl Debug for Player {
92 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93 write!(f, "Player({})", self.0)
94 }
95}
96
97impl Display for Player {
98 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
99 write!(f, "{}", self.0)
100 }
101}
102
103pub const fn player(i: u8) -> Player { Player::new(i) }
105
106pub const fn all_players_from(player: Player) -> [Player; 4] {
114 [player.add(P0), player.add(P1), player.add(P2), player.add(P3)]
115}
116
117pub const fn other_players_after(player: Player) -> [Player; 3] {
125 [player.add(P1), player.add(P2), player.add(P3)]
126}
127
128#[cfg(feature = "serde")]
129mod player_serde {
130 use core::fmt::Formatter;
131 use serde::{*};
132 use serde::de::{Error, Visitor};
133 use super::*;
134
135 impl Serialize for Player {
136 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> where S: Serializer {
137 s.serialize_u8(self.0.into())
138 }
139 }
140
141 impl<'de> Deserialize<'de> for Player {
142 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
143 struct PlayerVisitor;
144 impl<'a> Visitor<'a> for PlayerVisitor {
145 type Value = Player;
146
147 fn expecting(&self, f: &mut Formatter) -> core::fmt::Result {
148 write!(f, "0..=3")
149 }
150
151 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> where E: Error {
152 if (0..=3).contains(&v) {
153 Ok(Player(v as u8))
154 } else {
155 Err(E::custom("out of range"))
156 }
157 }
158 }
159 deserializer.deserialize_u8(PlayerVisitor)
160 }
161 }
162}