use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub trait AsCompact {
type Compacted<'a>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_>;
}
impl<T> AsCompact for &T
where
T: AsCompact + ?Sized,
{
type Compacted<'a>
= T::Compacted<'a>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
T::as_compacted(self)
}
}
pub trait FromCompact: Sized {
type Compacted;
fn from_compacted(compacted: Self::Compacted) -> Self;
}
pub fn serialize<'a, T, S>(value: &'a T, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
T: AsCompact + ?Sized,
<T as AsCompact>::Compacted<'a>: Serialize,
S: Serializer,
{
value.as_compacted().serialize(serializer)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> std::result::Result<T, D::Error>
where
T: FromCompact,
<T as FromCompact>::Compacted: Deserialize<'de>,
D: Deserializer<'de>,
{
let compacted = T::Compacted::deserialize(deserializer)?;
Ok(T::from_compacted(compacted))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Result<T, E> {
#[serde(rename = "_0")]
Ok(T),
#[serde(rename = "_1")]
Err(E),
}
impl<T, E> From<std::result::Result<T, E>> for Result<T, E> {
fn from(res: std::result::Result<T, E>) -> Self {
match res {
Ok(t) => Self::Ok(t),
Err(err) => Self::Err(err),
}
}
}
impl<T, E> From<Result<T, E>> for std::result::Result<T, E> {
fn from(compact: Result<T, E>) -> Self {
match compact {
Result::Ok(v) => std::result::Result::Ok(v),
Result::Err(err) => std::result::Result::Err(err),
}
}
}
impl<T, E> AsCompact for std::result::Result<T, E> {
type Compacted<'a>
= Result<&'a T, &'a E>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
match self {
Ok(value) => Result::Ok(value),
Err(err) => Result::Err(err),
}
}
}
impl<T, E> FromCompact for std::result::Result<T, E> {
type Compacted = Result<T, E>;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
const NANOS_PER_SEC: i128 = 1_000_000_000;
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(try_from = "(u64, u32)")]
pub struct Duration(pub u64, pub u32);
impl TryFrom<(u64, u32)> for Duration {
type Error = &'static str;
fn try_from((secs, nanos): (u64, u32)) -> std::result::Result<Self, Self::Error> {
if i128::from(nanos) >= NANOS_PER_SEC {
return Err("Duration nanoseconds out of range");
}
Ok(Self(secs, nanos))
}
}
impl From<std::time::Duration> for Duration {
fn from(duration: std::time::Duration) -> Self {
Self(duration.as_secs(), duration.subsec_nanos())
}
}
impl From<Duration> for std::time::Duration {
fn from(compact: Duration) -> Self {
assert!(i128::from(compact.1) < NANOS_PER_SEC, "Duration nanoseconds out of range");
std::time::Duration::new(compact.0, compact.1)
}
}
impl AsCompact for std::time::Duration {
type Compacted<'a> = Duration;
fn as_compacted(&self) -> Self::Compacted<'_> {
(*self).into()
}
}
impl FromCompact for std::time::Duration {
type Compacted = Duration;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(try_from = "(i64, u32)")]
pub struct SystemTime(pub i64, pub u32);
impl TryFrom<(i64, u32)> for SystemTime {
type Error = &'static str;
fn try_from((secs, nanos): (i64, u32)) -> std::result::Result<Self, Self::Error> {
let compact = Self(secs, nanos);
match compact.checked_into() {
Some(_) => Ok(compact),
None => Err("SystemTime out of range"),
}
}
}
impl SystemTime {
fn checked_into(self) -> Option<std::time::SystemTime> {
if i128::from(self.1) >= NANOS_PER_SEC {
return None;
}
let secs = std::time::Duration::from_secs(self.0.unsigned_abs());
let subsec = std::time::Duration::from_nanos(self.1.into());
if self.0 >= 0 {
std::time::UNIX_EPOCH.checked_add(secs)?.checked_add(subsec)
} else {
std::time::UNIX_EPOCH.checked_sub(secs)?.checked_add(subsec)
}
}
}
impl From<std::time::SystemTime> for SystemTime {
fn from(time: std::time::SystemTime) -> Self {
let nanos: i128 = match time.duration_since(std::time::UNIX_EPOCH) {
Ok(duration) => duration.as_nanos() as i128,
Err(err) => -(err.duration().as_nanos() as i128),
};
let secs = i64::try_from(nanos.div_euclid(NANOS_PER_SEC)).expect("SystemTime out of range");
Self(secs, nanos.rem_euclid(NANOS_PER_SEC) as u32)
}
}
impl From<SystemTime> for std::time::SystemTime {
fn from(compact: SystemTime) -> Self {
compact.checked_into().expect("SystemTime out of range")
}
}
impl AsCompact for std::time::SystemTime {
type Compacted<'a> = SystemTime;
fn as_compacted(&self) -> Self::Compacted<'_> {
(*self).into()
}
}
impl FromCompact for std::time::SystemTime {
type Compacted = SystemTime;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Range<Idx>(pub Idx, pub Idx);
impl<Idx> From<std::ops::Range<Idx>> for Range<Idx> {
fn from(range: std::ops::Range<Idx>) -> Self {
Self(range.start, range.end)
}
}
impl<Idx> From<Range<Idx>> for std::ops::Range<Idx> {
fn from(compact: Range<Idx>) -> Self {
compact.0..compact.1
}
}
impl<Idx> AsCompact for std::ops::Range<Idx> {
type Compacted<'a>
= Range<&'a Idx>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
Range(&self.start, &self.end)
}
}
impl<Idx> FromCompact for std::ops::Range<Idx> {
type Compacted = Range<Idx>;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct RangeInclusive<Idx>(pub Idx, pub Idx);
impl<Idx> From<std::ops::RangeInclusive<Idx>> for RangeInclusive<Idx> {
fn from(range: std::ops::RangeInclusive<Idx>) -> Self {
let (start, end) = range.into_inner();
Self(start, end)
}
}
impl<Idx> From<RangeInclusive<Idx>> for std::ops::RangeInclusive<Idx> {
fn from(compact: RangeInclusive<Idx>) -> Self {
Self::new(compact.0, compact.1)
}
}
impl<Idx> AsCompact for std::ops::RangeInclusive<Idx> {
type Compacted<'a>
= RangeInclusive<&'a Idx>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
RangeInclusive(self.start(), self.end())
}
}
impl<Idx> FromCompact for std::ops::RangeInclusive<Idx> {
type Compacted = RangeInclusive<Idx>;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct RangeFrom<Idx>(pub Idx);
impl<Idx> From<std::ops::RangeFrom<Idx>> for RangeFrom<Idx> {
fn from(range: std::ops::RangeFrom<Idx>) -> Self {
Self(range.start)
}
}
impl<Idx> From<RangeFrom<Idx>> for std::ops::RangeFrom<Idx> {
fn from(compact: RangeFrom<Idx>) -> Self {
compact.0..
}
}
impl<Idx> AsCompact for std::ops::RangeFrom<Idx> {
type Compacted<'a>
= RangeFrom<&'a Idx>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
RangeFrom(&self.start)
}
}
impl<Idx> FromCompact for std::ops::RangeFrom<Idx> {
type Compacted = RangeFrom<Idx>;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct RangeTo<Idx>(pub Idx);
impl<Idx> From<std::ops::RangeTo<Idx>> for RangeTo<Idx> {
fn from(range: std::ops::RangeTo<Idx>) -> Self {
Self(range.end)
}
}
impl<Idx> From<RangeTo<Idx>> for std::ops::RangeTo<Idx> {
fn from(compact: RangeTo<Idx>) -> Self {
..compact.0
}
}
impl<Idx> AsCompact for std::ops::RangeTo<Idx> {
type Compacted<'a>
= RangeTo<&'a Idx>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
RangeTo(&self.end)
}
}
impl<Idx> FromCompact for std::ops::RangeTo<Idx> {
type Compacted = RangeTo<Idx>;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Bound<T> {
#[serde(rename = "_0")]
Unbounded,
#[serde(rename = "_1")]
Included(T),
#[serde(rename = "_2")]
Excluded(T),
}
impl<T> From<std::ops::Bound<T>> for Bound<T> {
fn from(bound: std::ops::Bound<T>) -> Self {
match bound {
std::ops::Bound::Unbounded => Self::Unbounded,
std::ops::Bound::Included(value) => Self::Included(value),
std::ops::Bound::Excluded(value) => Self::Excluded(value),
}
}
}
impl<T> From<Bound<T>> for std::ops::Bound<T> {
fn from(compact: Bound<T>) -> Self {
match compact {
Bound::Unbounded => Self::Unbounded,
Bound::Included(value) => Self::Included(value),
Bound::Excluded(value) => Self::Excluded(value),
}
}
}
impl<T> AsCompact for std::ops::Bound<T> {
type Compacted<'a>
= Bound<&'a T>
where
Self: 'a;
fn as_compacted(&self) -> Self::Compacted<'_> {
match self {
std::ops::Bound::Unbounded => Bound::Unbounded,
std::ops::Bound::Included(value) => Bound::Included(value),
std::ops::Bound::Excluded(value) => Bound::Excluded(value),
}
}
}
impl<T> FromCompact for std::ops::Bound<T> {
type Compacted = Bound<T>;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum IpAddr {
#[serde(rename = "_0")]
V4(std::net::Ipv4Addr),
#[serde(rename = "_1")]
V6(std::net::Ipv6Addr),
}
impl From<std::net::IpAddr> for IpAddr {
fn from(addr: std::net::IpAddr) -> Self {
match addr {
std::net::IpAddr::V4(addr) => Self::V4(addr),
std::net::IpAddr::V6(addr) => Self::V6(addr),
}
}
}
impl From<IpAddr> for std::net::IpAddr {
fn from(compact: IpAddr) -> Self {
match compact {
IpAddr::V4(addr) => Self::V4(addr),
IpAddr::V6(addr) => Self::V6(addr),
}
}
}
impl AsCompact for std::net::IpAddr {
type Compacted<'a> = IpAddr;
fn as_compacted(&self) -> Self::Compacted<'_> {
(*self).into()
}
}
impl FromCompact for std::net::IpAddr {
type Compacted = IpAddr;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct SocketAddrV6(pub std::net::Ipv6Addr, pub u16, pub u32, pub u32);
impl From<std::net::SocketAddrV6> for SocketAddrV6 {
fn from(addr: std::net::SocketAddrV6) -> Self {
Self(*addr.ip(), addr.port(), addr.flowinfo(), addr.scope_id())
}
}
impl From<SocketAddrV6> for std::net::SocketAddrV6 {
fn from(compact: SocketAddrV6) -> Self {
Self::new(compact.0, compact.1, compact.2, compact.3)
}
}
impl AsCompact for std::net::SocketAddrV6 {
type Compacted<'a> = SocketAddrV6;
fn as_compacted(&self) -> Self::Compacted<'_> {
(*self).into()
}
}
impl FromCompact for std::net::SocketAddrV6 {
type Compacted = SocketAddrV6;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum SocketAddr {
#[serde(rename = "_0")]
V4(std::net::SocketAddrV4),
#[serde(rename = "_1")]
V6(SocketAddrV6),
}
impl From<std::net::SocketAddr> for SocketAddr {
fn from(addr: std::net::SocketAddr) -> Self {
match addr {
std::net::SocketAddr::V4(addr) => Self::V4(addr),
std::net::SocketAddr::V6(addr) => Self::V6(addr.into()),
}
}
}
impl From<SocketAddr> for std::net::SocketAddr {
fn from(compact: SocketAddr) -> Self {
match compact {
SocketAddr::V4(addr) => Self::V4(addr),
SocketAddr::V6(addr) => Self::V6(addr.into()),
}
}
}
impl AsCompact for std::net::SocketAddr {
type Compacted<'a> = SocketAddr;
fn as_compacted(&self) -> Self::Compacted<'_> {
(*self).into()
}
}
impl FromCompact for std::net::SocketAddr {
type Compacted = SocketAddr;
fn from_compacted(compacted: Self::Compacted) -> Self {
compacted.into()
}
}