alpaca-core 0.23.8

Shared primitives for the alpaca-rust workspace
Documentation
use serde::{Deserialize, Deserializer, Serializer, de};

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum StringOrNumber {
    String(String),
    Number(serde_json::Number),
}

fn parse_u32<E>(value: StringOrNumber) -> Result<u32, E>
where
    E: de::Error,
{
    let raw = match value {
        StringOrNumber::String(value) => value,
        StringOrNumber::Number(value) => value.to_string(),
    };

    raw.parse::<u32>()
        .map_err(|error| E::custom(format!("invalid integer value `{raw}`: {error}")))
}

pub fn deserialize_u32_from_string_or_number<'de, D>(deserializer: D) -> Result<u32, D::Error>
where
    D: Deserializer<'de>,
{
    parse_u32(StringOrNumber::deserialize(deserializer)?)
}

pub fn deserialize_option_u32_from_string_or_number<'de, D>(
    deserializer: D,
) -> Result<Option<u32>, D::Error>
where
    D: Deserializer<'de>,
{
    Option::<StringOrNumber>::deserialize(deserializer)?
        .map(parse_u32)
        .transpose()
}

pub mod string_contract {
    use super::*;

    pub fn serialize_u32<S>(value: &u32, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&value.to_string())
    }

    pub fn serialize_option_u32<S>(value: &Option<u32>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match value {
            Some(value) => serialize_u32(value, serializer),
            None => serializer.serialize_none(),
        }
    }
}