118 lines
3.0 KiB
Rust
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))
|
|
}
|