1pub mod channel;
6pub mod graphics;
7pub mod mixin;
8pub mod time;
9
10pub mod minor_command;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub enum PlayerMode {
20 Single,
22 Two,
24 Double,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub enum JudgeLevel {
37 VeryHard,
39 Hard,
41 Normal,
43 Easy,
45 OtherInt(i64),
48}
49
50impl From<i64> for JudgeLevel {
51 fn from(value: i64) -> Self {
52 match value {
53 0 => Self::VeryHard,
54 1 => Self::Hard,
55 2 => Self::Normal,
56 3 => Self::Easy,
57 val => Self::OtherInt(val),
58 }
59 }
60}
61
62impl<'a> TryFrom<&'a str> for JudgeLevel {
63 type Error = &'a str;
64 fn try_from(value: &'a str) -> core::result::Result<Self, Self::Error> {
65 value.parse::<i64>().map(Self::from).map_err(|_| value)
66 }
67}
68
69impl std::fmt::Display for JudgeLevel {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 match self {
72 Self::VeryHard => write!(f, "0"),
73 Self::Hard => write!(f, "1"),
74 Self::Normal => write!(f, "2"),
75 Self::Easy => write!(f, "3"),
76 Self::OtherInt(value) => write!(f, "{value}"),
77 }
78 }
79}
80
81pub(crate) const fn char_to_base62(ch: char) -> Option<u8> {
82 match ch {
83 '0'..='9' | 'A'..='Z' | 'a'..='z' => Some(ch as u32 as u8),
84 _ => None,
85 }
86}
87
88pub(crate) fn base62_to_byte(base62: u8) -> u8 {
89 match base62 {
90 b'0'..=b'9' => base62 - b'0',
91 b'A'..=b'Z' => base62 - b'A' + 10,
92 b'a'..=b'z' => base62 - b'a' + 36,
93 _ => unreachable!(),
94 }
95}
96
97#[test]
98fn test_base62() {
99 assert_eq!(char_to_base62('/'), None);
100 assert_eq!(char_to_base62('0'), Some(b'0'));
101 assert_eq!(char_to_base62('9'), Some(b'9'));
102 assert_eq!(char_to_base62(':'), None);
103 assert_eq!(char_to_base62('@'), None);
104 assert_eq!(char_to_base62('A'), Some(b'A'));
105 assert_eq!(char_to_base62('Z'), Some(b'Z'));
106 assert_eq!(char_to_base62('['), None);
107 assert_eq!(char_to_base62('`'), None);
108 assert_eq!(char_to_base62('a'), Some(b'a'));
109 assert_eq!(char_to_base62('z'), Some(b'z'));
110 assert_eq!(char_to_base62('{'), None);
111}
112
113#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118pub struct ObjId([u8; 2]);
119
120impl std::fmt::Debug for ObjId {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 f.debug_tuple("ObjId")
123 .field(&format!("{}{}", self.0[0] as char, self.0[1] as char))
124 .finish()
125 }
126}
127
128impl std::fmt::Display for ObjId {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 write!(f, "{}{}", self.0[0] as char, self.0[1] as char)
131 }
132}
133
134impl TryFrom<[char; 2]> for ObjId {
135 type Error = [char; 2];
136 fn try_from(value: [char; 2]) -> core::result::Result<Self, Self::Error> {
137 Ok(Self([
138 char_to_base62(value[0]).ok_or(value)?,
139 char_to_base62(value[1]).ok_or(value)?,
140 ]))
141 }
142}
143
144impl TryFrom<[u8; 2]> for ObjId {
145 type Error = [u8; 2];
146 fn try_from(value: [u8; 2]) -> core::result::Result<Self, Self::Error> {
147 <Self as TryFrom<[char; 2]>>::try_from([value[0] as char, value[1] as char])
148 .map_err(|_| value)
149 }
150}
151
152impl<'a> TryFrom<&'a str> for ObjId {
153 type Error = &'a str;
154 fn try_from(value: &'a str) -> core::result::Result<Self, Self::Error> {
155 if value.len() != 2 {
156 return Err(value);
157 }
158 let mut chars = value.bytes();
159 let [Some(ch1), Some(ch2), None] = [chars.next(), chars.next(), chars.next()] else {
160 return Err(value);
161 };
162 Self::try_from([ch1, ch2]).map_err(|_| value)
163 }
164}
165
166impl From<ObjId> for u16 {
167 fn from(value: ObjId) -> Self {
168 base62_to_byte(value.0[0]) as u16 * 62 + base62_to_byte(value.0[1]) as u16
169 }
170}
171
172impl From<ObjId> for u32 {
173 fn from(value: ObjId) -> Self {
174 Into::<u16>::into(value) as u32
175 }
176}
177
178impl From<ObjId> for u64 {
179 fn from(value: ObjId) -> Self {
180 Into::<u16>::into(value) as u64
181 }
182}
183
184impl ObjId {
185 #[must_use]
187 pub const fn null() -> Self {
188 Self([0, 0])
189 }
190
191 #[must_use]
193 pub fn is_null(self) -> bool {
194 self.0 == [0, 0]
195 }
196
197 #[must_use]
199 pub fn as_u16(self) -> u16 {
200 self.into()
201 }
202
203 #[must_use]
205 pub fn as_u32(self) -> u32 {
206 self.into()
207 }
208
209 #[must_use]
211 pub fn as_u64(self) -> u64 {
212 self.into()
213 }
214
215 pub const fn make_uppercase(&mut self) {
217 self.0[0] = self.0[0].to_ascii_uppercase();
218 self.0[1] = self.0[1].to_ascii_uppercase();
219 }
220}
221
222#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
225pub struct Volume {
226 pub relative_percent: u8,
228}
229
230impl Default for Volume {
231 fn default() -> Self {
232 Self {
233 relative_percent: 100,
234 }
235 }
236}
237
238#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
240#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
241pub enum PoorMode {
242 #[default]
244 Interrupt,
245 Overlay,
247 Hidden,
249}
250
251#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
253#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
254pub enum LnType {
255 #[default]
257 Rdm,
258 Mgq,
260}
261
262#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
264#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
265#[repr(u8)]
266pub enum LnMode {
267 #[default]
269 Ln = 1,
270 Cn = 2,
272 Hcn = 3,
274}
275
276impl From<LnMode> for u8 {
277 fn from(mode: LnMode) -> u8 {
278 match mode {
279 LnMode::Ln => 1,
280 LnMode::Cn => 2,
281 LnMode::Hcn => 3,
282 }
283 }
284}
285
286impl TryFrom<u8> for LnMode {
287 type Error = u8;
288 fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
289 Ok(match value {
290 1 => Self::Ln,
291 2 => Self::Cn,
292 3 => Self::Hcn,
293 _ => return Err(value),
294 })
295 }
296}