magnetar/magnetar_sdk/src/util_types.rs

118 lines
3.0 KiB
Rust

use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::hash::Hash;
use ts_rs::TS;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct U64Range<const MIN: u64, const MAX: u64>(u64);
impl<const MIN: u64, const MAX: u64> TS for U64Range<MIN, MAX> {
const EXPORT_TO: Option<&'static str> = Some("bindings/util/u64_range.ts");
fn decl() -> String {
<usize as TS>::decl()
}
fn name() -> String {
<usize as TS>::name()
}
fn dependencies() -> Vec<ts_rs::Dependency> {
vec![]
}
fn transparent() -> bool {
true
}
}
impl<const MIN: u64, const MAX: u64> Serialize for U64Range<MIN, MAX> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_u64(self.0)
}
}
impl<'de, const MIN: u64, const MAX: u64> serde::Deserialize<'de> for U64Range<MIN, MAX> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let v = u64::deserialize(deserializer)?;
if v < MIN || v > MAX {
return Err(serde::de::Error::custom("out of range"));
}
Ok(U64Range(v))
}
}
impl<const MIN: u64, const MAX: u64> std::ops::Deref for U64Range<MIN, MAX> {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const MIN: u64, const MAX: u64> From<U64Range<MIN, MAX>> for u64 {
fn from(v: U64Range<MIN, MAX>) -> Self {
v.0
}
}
impl<const MIN: u64, const MAX: u64> std::fmt::Display for U64Range<MIN, MAX> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
pub struct OutOfRange;
impl<const MIN: u64, const MAX: u64> TryFrom<u64> for U64Range<MIN, MAX> {
type Error = OutOfRange;
fn try_from(value: u64) -> Result<Self, Self::Error> {
if value < MIN || value > MAX {
return Err(OutOfRange);
}
Ok(U64Range(value))
}
}
pub(crate) fn deserialize_array_urlenc<'de, D, T: Eq + Hash>(
deserializer: D,
) -> Result<Vec<T>, D::Error>
where
D: serde::Deserializer<'de>,
T: DeserializeOwned,
{
let str_raw = String::deserialize(deserializer)?;
let parts = serde_urlencoded::from_str::<Vec<(T, String)>>(&str_raw)
.map_err(serde::de::Error::custom)?
.into_iter()
.map(|(k, _)| k)
.collect::<Vec<_>>();
Ok(parts)
}
pub(crate) fn deserialize_opt_array_urlenc<'de, D, T: Eq + Hash>(
deserializer: D,
) -> Result<Option<Vec<T>>, D::Error>
where
D: serde::Deserializer<'de>,
T: DeserializeOwned,
{
let Some(str_raw) = Option::<String>::deserialize(deserializer)? else {
return Ok(None);
};
let parts = serde_urlencoded::from_str::<Vec<(T, String)>>(&str_raw)
.map_err(serde::de::Error::custom)?
.into_iter()
.map(|(k, _)| k)
.collect::<Vec<_>>();
Ok(Some(parts))
}