hyli-model 0.14.0

Hyli datamodel
Documentation
use std::{
    ops::{Add, Sub},
    time::Duration,
};

use borsh::{BorshDeserialize, BorshSerialize};
use derive_more::Display;
use serde::{Deserialize, Serialize};

pub mod hex_bytes {
    use serde::{Deserialize, Deserializer, Serializer};

    pub fn serialize<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&hex::encode(bytes))
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        let normalized = super::normalize_hex_string(&s);
        hex::decode(&normalized).map_err(serde::de::Error::custom)
    }
}

fn normalize_hex_string(s: &str) -> String {
    let trimmed = s.strip_prefix("0x").unwrap_or(s);
    if trimmed.len() % 2 == 1 {
        format!("0{trimmed}")
    } else {
        trimmed.to_string()
    }
}

pub fn decode_hex_string_checked(s: &str) -> Result<Vec<u8>, hex::FromHexError> {
    let normalized = normalize_hex_string(s);
    hex::decode(&normalized)
}

#[derive(
    Debug,
    Clone,
    Deserialize,
    Serialize,
    PartialEq,
    Eq,
    BorshDeserialize,
    BorshSerialize,
    PartialOrd,
    Ord,
    Default,
    Display,
    Hash,
)]
#[cfg_attr(feature = "full", derive(utoipa::ToSchema))]
pub struct TimestampMs(pub u128);

impl TimestampMs {
    pub const ZERO: TimestampMs = TimestampMs(0);
}

impl Add<Duration> for TimestampMs {
    type Output = TimestampMs;

    fn add(self, rhs: Duration) -> Self::Output {
        TimestampMs(self.0 + rhs.as_millis())
    }
}

impl Sub<TimestampMs> for TimestampMs {
    type Output = Duration;

    fn sub(self, rhs: TimestampMs) -> Duration {
        Duration::from_millis((self.0 - rhs.0) as u64)
    }
}

impl Sub<Duration> for TimestampMs {
    type Output = TimestampMs;

    fn sub(self, rhs: Duration) -> TimestampMs {
        TimestampMs(self.0 - rhs.as_millis())
    }
}