fix: GameTime not being json-serializable

This commit is contained in:
emilis 2026-02-19 00:16:43 +00:00
parent 14e8f369ea
commit f280f35305
No known key found for this signature in database
1 changed files with 63 additions and 2 deletions

View File

@ -27,7 +27,10 @@ use core::{
use chrono::{DateTime, Utc};
use rand::{Rng, seq::SliceRandom};
use serde::{Deserialize, Serialize};
use serde::{
Deserialize, Serialize,
de::{Expected, Unexpected},
};
use uuid::Uuid;
use crate::{
@ -482,12 +485,70 @@ pub enum Maybe {
Maybe,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub enum GameTime {
Day { number: NonZeroU8 },
Night { number: u8 },
}
impl Serialize for GameTime {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
GameTime::Day { number } => format!("day_{number}"),
GameTime::Night { number } => format!("night_{number}"),
}
.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for GameTime {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
enum ExpectedGameTime {
Format,
NumberU8,
NonZeroU8,
}
impl Expected for ExpectedGameTime {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str(match self {
Self::Format => "expected day_{num_nz} or night_{num}, where {num_nz} is a nonzero u8, and {num} is a u8",
Self::NumberU8 => "expected a u8 after day_ or night_",
Self::NonZeroU8 => "expected a non-zero day number",
})
}
}
let s = crate::limited::ClampedString::<5, 9>::deserialize(deserializer)?;
let (day_or_night, number) = s.split_once('_').ok_or(serde::de::Error::invalid_value(
Unexpected::Str(s.as_str()),
&ExpectedGameTime::Format,
))?;
let parsed_number = number.parse::<u8>().map_err(|_| {
serde::de::Error::invalid_value(Unexpected::Str(number), &ExpectedGameTime::NumberU8)
})?;
match day_or_night {
"day" => NonZeroU8::new(parsed_number)
.map(|number| GameTime::Day { number })
.ok_or(serde::de::Error::invalid_value(
Unexpected::Str(number),
&ExpectedGameTime::NonZeroU8,
)),
"night" => Ok(GameTime::Night {
number: parsed_number,
}),
_ => Err(serde::de::Error::invalid_value(
Unexpected::Str(day_or_night),
&ExpectedGameTime::Format,
)),
}
}
}
impl PartialOrd for GameTime {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))