microversus_codex 0.1.8

Types and definitions for interfacing with the microversus system
Documentation
use serde::{Deserialize, Serialize};

use crate::MicroversusError;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RoundConfig;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WorldDetailsTmpl<Metadata, Config> {
    pub slug: String,
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub round_id: Option<u32>,
    pub metadata: Metadata,
    pub config: Config,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub round_start: Option<u32>,
}

pub type RawWorldDetails = WorldDetailsTmpl<Option<String>, Option<String>>;
pub type WorldDetails = WorldDetailsTmpl<Option<serde_json::Value>, Option<RoundConfig>>;

impl TryFrom<RawWorldDetails> for WorldDetails {
    type Error = MicroversusError;

    fn try_from(value: RawWorldDetails) -> Result<Self, Self::Error> {
        let metadata: Option<serde_json::Value> = value
            .metadata
            .map(|t| serde_json::from_str(&t))
            .transpose()?;

        let config: Option<RoundConfig> =
            value.config.map(|t| serde_json::from_str(&t)).transpose()?;

        Ok(WorldDetails {
            slug: value.slug.clone(),
            name: value.name.clone(),
            round_id: value.round_id,
            metadata,
            config,
            round_start: value.round_start,
        })
    }
}

impl TryFrom<&RawWorldDetails> for WorldDetails {
    type Error = MicroversusError;

    fn try_from(value: &RawWorldDetails) -> Result<Self, Self::Error> {
        // Delegate by cloning and calling existing implementation
        WorldDetails::try_from(value.clone())
    }
}