mcsr_ranked_api/pagination/
mod.rs1use std::{error::Error, fmt::Display, num::NonZeroU8};
2
3use serde::Serialize;
4
5use crate::types::MatchId;
6
7const MAX_COUNT: u8 = 100;
8
9#[cfg(test)]
10mod tests;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13pub struct Pagination {
14 pub count: NonZeroU8,
15 #[serde(flatten)]
16 pub position: RelativePos,
17}
18
19impl Default for Pagination {
20 fn default() -> Self {
21 Self {
22 count: const { NonZeroU8::new(20).unwrap() },
23 position: Default::default(),
24 }
25 }
26}
27
28impl Pagination {
29 pub fn new(count: u8, position: RelativePos) -> Option<Self> {
31 NonZeroU8::new(count)
32 .filter(|_| count <= MAX_COUNT)
33 .map(|count| Self { count, position })
34 }
35
36 pub unsafe fn new_unchecked(count: u8, position: RelativePos) -> Self {
46 Self {
47 count: unsafe { NonZeroU8::new_unchecked(count) },
48 position,
49 }
50 }
51
52 pub fn count(count: u8) -> Option<Self> {
54 NonZeroU8::new(count).map(|count| Self {
55 count,
56 ..Default::default()
57 })
58 }
59
60 pub unsafe fn count_unchecked(count: u8) -> Self {
70 Self {
71 count: unsafe { NonZeroU8::new_unchecked(count) },
72 ..Default::default()
73 }
74 }
75}
76
77impl From<RelativePos> for Pagination {
78 fn from(position: RelativePos) -> Self {
79 Self {
80 position,
81 ..Default::default()
82 }
83 }
84}
85
86#[derive(Debug, Clone)]
87pub struct RelativePosError {
88 pub before: MatchId,
90 pub after: MatchId,
92}
93impl Display for RelativePosError {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 write!(
96 f,
97 "Cannot create RelativePos, before = {} > after = {}",
98 self.before, self.after
99 )
100 }
101}
102impl Error for RelativePosError {}
103
104#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize)]
105#[serde(rename_all = "lowercase")]
106pub struct RelativePos {
107 #[serde(skip_serializing_if = "Option::is_none")]
108 before: Option<MatchId>,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 after: Option<MatchId>,
111}
112impl RelativePos {
113 pub fn new_checked(before: MatchId, after: MatchId) -> Result<Self, RelativePosError> {
115 if after > before {
116 Err(RelativePosError { before, after })
117 } else {
118 Ok(Self {
119 before: Some(before),
120 after: Some(after),
121 })
122 }
123 }
124 pub fn new(before: MatchId, after: MatchId) -> Self {
128 Self {
129 before: Some(before),
130 after: Some(after),
131 }
132 }
133 pub fn before(before: MatchId) -> Self {
135 Self {
136 before: Some(before),
137 after: None,
138 }
139 }
140 pub fn after(after: MatchId) -> Self {
142 Self {
143 before: None,
144 after: Some(after),
145 }
146 }
147}