1use crate::encode::Encode;
2use alloc::borrow::Cow;
3use core::fmt::Display;
4use serde::{Deserialize, Serialize};
5
6pub enum BadgeValidationError {
7 EmptyName,
8 NameTooLong,
9 DescrTooLong,
10 TooMuchXp,
11}
12
13impl BadgeValidationError {
14 #[must_use]
15 pub const fn as_str(&self) -> &'static str {
16 match self {
17 Self::EmptyName => "name must not be empty",
18 Self::NameTooLong => "name is too long",
19 Self::DescrTooLong => "descr is too long",
20 Self::TooMuchXp => "one badge cannot reward more than 200 XP",
21 }
22 }
23}
24
25impl Display for BadgeValidationError {
26 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27 write!(f, "{}", self.as_str())
28 }
29}
30
31#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
32pub struct Badges<'a> {
33 #[serde(borrow)]
35 pub badges: Cow<'a, [Badge<'a>]>,
36}
37
38impl<'a> Badges<'a> {
39 #[must_use]
40 pub const fn new(badges: Cow<'a, [Badge<'a>]>) -> Self {
41 Self { badges }
42 }
43}
44
45impl<'a> Encode<'a> for Badges<'a> {}
46
47#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
48pub struct Badge<'a> {
49 pub position: u16,
53
54 pub xp: u8,
56
57 pub hidden: u16,
62
63 pub name: &'a str,
65
66 pub descr: &'a str,
68}
69
70impl Badge<'_> {
71 pub const fn validate(&self) -> Result<(), BadgeValidationError> {
77 if self.name.is_empty() {
78 return Err(BadgeValidationError::EmptyName);
79 }
80 if self.name.len() > 64 {
81 return Err(BadgeValidationError::NameTooLong);
82 }
83 if self.descr.len() > 256 {
84 return Err(BadgeValidationError::DescrTooLong);
85 }
86 if self.xp > 200 {
87 return Err(BadgeValidationError::TooMuchXp);
88 }
89 Ok(())
90 }
91}