mcsr_ranked_api/pagination/
mod.rs

1use std::num::NonZeroU8;
2
3use serde::Serialize;
4
5use crate::types::MatchId;
6
7const MAX_COUNT: u8 = 50;
8
9#[cfg(test)]
10mod tests;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13pub struct Pagination {
14	count: NonZeroU8,
15	#[serde(flatten)]
16	#[serde(skip_serializing_if = "Option::is_none")]
17	position: Option<RelativePos>,
18}
19
20impl Default for Pagination {
21	fn default() -> Self {
22		Self {
23			count: const { NonZeroU8::new(20).unwrap() },
24			position: None,
25		}
26	}
27}
28
29impl Pagination {
30	/// Attempt to construct a pagination given a `count` and `position`
31	pub fn new(count: u8, position: RelativePos) -> Option<Self> {
32		NonZeroU8::new(count)
33			.filter(|_| count <= MAX_COUNT)
34			.map(|count| Self {
35				count,
36				position: Some(position),
37			})
38	}
39
40	/// Create a new pagination given a `count` and `position`
41	/// without checking for `count` bounds
42	///
43	/// # Safety
44	/// this function calls `NonZeroU8::new_unchecked`. Passing a value outside the [1; 50] range for `count`
45	/// will result in undefined behavior
46	pub unsafe fn new_unchecked(count: u8, position: RelativePos) -> Self {
47		Self {
48			count: unsafe { NonZeroU8::new_unchecked(count) },
49			position: Some(position),
50		}
51	}
52
53	/// Attempt to construct a pagination given a `count` without relative position
54	pub fn count(count: u8) -> Option<Self> {
55		NonZeroU8::new(count).map(|count| Self {
56			count,
57			position: None,
58		})
59	}
60
61	/// Create a new pagination given a `count` without a relative position
62	/// without checking for `count` bounds
63	///
64	/// # Safety
65	/// this function calls `NonZeroU8::new_unchecked`. Passing a value outside the [1; 50] range for `count`
66	/// will result in undefined behavior
67	pub unsafe fn count_unchecked(count: u8) -> Self {
68		Self {
69			count: unsafe { NonZeroU8::new_unchecked(count) },
70			position: None,
71		}
72	}
73}
74
75impl From<RelativePos> for Pagination {
76	fn from(position: RelativePos) -> Self {
77		Self {
78			position: Some(position),
79			..Default::default()
80		}
81	}
82}
83impl From<Option<RelativePos>> for Pagination {
84	fn from(position: Option<RelativePos>) -> Self {
85		Self {
86			position,
87			..Default::default()
88		}
89	}
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
93#[serde(rename_all = "lowercase")]
94pub enum RelativePos {
95	Before(MatchId),
96	After(MatchId),
97}