mcsr_ranked_api/types/
mod.rs

1use std::{
2	collections::HashMap,
3	fmt::{self, Display},
4};
5
6use serde::{Deserialize, Deserializer, de};
7#[cfg(feature = "serialize")]
8use serde::{Serialize, ser::SerializeMap};
9use serde_json::Value;
10use uuid::Uuid;
11
12#[cfg(test)]
13mod tests;
14
15pub type Elo = u16;
16pub type EloChange = i16;
17pub type PhasePoints = u16;
18pub type Rank = u32;
19pub type Season = u8;
20pub type Phase = u8;
21#[cfg(feature = "matches")]
22pub type MatchId = u64;
23#[cfg(feature = "weekly_races")]
24pub type WeeklyRaceId = u32;
25pub type MinecraftSeed = u64;
26
27#[cfg_attr(feature = "serialize", derive(Serialize))]
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
29#[serde(transparent)]
30pub struct Time(pub u64);
31
32impl Time {
33	pub const fn new(value: u64) -> Self {
34		Self(value)
35	}
36	pub const fn millis(&self) -> u64 {
37		self.0 % 1000
38	}
39	pub const fn seconds(&self) -> u64 {
40		(self.0 / 1000) % 60
41	}
42	pub const fn minutes(&self) -> u64 {
43		(self.0 / 60000) % 60
44	}
45	pub const fn hours(&self) -> u64 {
46		self.0 / 3600000
47	}
48}
49
50#[doc(hidden)]
51/// Result with this crate's own `Error` type as default
52pub type Result<T, E = Error> = std::result::Result<T, E>;
53
54#[doc(hidden)]
55/// Error returned by a request to the API
56#[derive(Debug)]
57pub enum Error {
58	/// Ranked API error
59	Api(Value),
60	/// Reqwest library error
61	Reqwest(reqwest::Error),
62}
63
64impl PartialEq for Error {
65	fn eq(&self, other: &Self) -> bool {
66		match (self, other) {
67			(Error::Api(lhs), Error::Api(rhs)) => lhs == rhs,
68			(Error::Reqwest(lhs), Error::Reqwest(rhs)) => lhs.to_string() == rhs.to_string(),
69			_ => false,
70		}
71	}
72}
73impl Eq for Error {}
74
75impl From<reqwest::Error> for Error {
76	fn from(value: reqwest::Error) -> Self {
77		Self::Reqwest(value)
78	}
79}
80
81impl Display for Error {
82	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83		match self {
84			Error::Api(api_err) => write!(f, "API Error: {api_err}"),
85			Error::Reqwest(req_err) => write!(f, "Reqwest Error: {req_err}"),
86		}
87	}
88}
89impl std::error::Error for Error {}
90
91#[derive(Debug, PartialEq, Eq, Deserialize)]
92#[serde(tag = "status", content = "data", rename_all = "camelCase")]
93pub(crate) enum DeResult<T> {
94	Success(T),
95	Error(Value),
96}
97
98impl<T> From<DeResult<T>> for Result<T> {
99	fn from(value: DeResult<T>) -> Self {
100		match value {
101			DeResult::Success(t) => Ok(t),
102			DeResult::Error(error) => Err(Error::Api(error)),
103		}
104	}
105}
106
107/// Container for ranked and casual values
108#[cfg_attr(feature = "serialize", derive(Serialize))]
109#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
110pub struct RankedAndCasual<T = u64> {
111	pub ranked: T,
112	pub casual: T,
113}
114
115/// Container for UUIDs and data of exactly two players
116#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117pub struct TwoUserData<T> {
118	pub user_1_uuid: Uuid,
119	pub user_1_data: T,
120	pub user_2_uuid: Uuid,
121	pub user_2_data: T,
122}
123impl<T> TwoUserData<T> {
124	/// First user's UUID and data
125	pub fn user_1(&self) -> (Uuid, &T) {
126		(self.user_1_uuid, &self.user_1_data)
127	}
128	/// Second user's UUID and data
129	pub fn user_2(&self) -> (Uuid, &T) {
130		(self.user_2_uuid, &self.user_2_data)
131	}
132}
133
134impl<'de, T: Deserialize<'de>> Deserialize<'de> for TwoUserData<T> {
135	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136	where
137		D: Deserializer<'de>,
138	{
139		let mut entries = HashMap::<Uuid, T>::deserialize(deserializer)?
140			.into_iter()
141			.collect::<Vec<_>>();
142		entries.sort_by_key(|(uuid, _)| *uuid);
143		let [(user_1_uuid, user_1_data), (user_2_uuid, user_2_data)] = entries
144			.try_into()
145			.map_err(|err: Vec<_>| de::Error::invalid_length(err.len(), &"2"))?;
146		Ok(TwoUserData {
147			user_1_uuid,
148			user_1_data,
149			user_2_uuid,
150			user_2_data,
151		})
152	}
153}
154#[cfg(feature = "serialize")]
155impl<T: Serialize> Serialize for TwoUserData<T> {
156	fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
157	where
158		S: serde::Serializer,
159	{
160		let mut map = serializer.serialize_map(Some(2))?;
161		map.serialize_entry(&self.user_1_uuid, &self.user_1_data)?;
162		map.serialize_entry(&self.user_2_uuid, &self.user_2_data)?;
163		map.end()
164	}
165}