use chrono::TimeDelta;
use miniserde::de::{Deserialize, Seq, Visitor};
use miniserde::ser::{Fragment, Seq as SerSeq};
pub fn begin(out: &mut Option<TimeDelta>) -> &mut dyn Visitor {
Place::new(out)
}
pub fn serialize(value: &TimeDelta) -> Fragment<'_> {
let secs = value.num_seconds();
let nanos = value.subsec_nanos();
Fragment::Seq(Box::new(TimeDeltaSeq {
values: vec![secs, nanos as i64],
index: 0,
}))
}
struct TimeDeltaSeq {
values: Vec<i64>,
index: usize,
}
impl SerSeq for TimeDeltaSeq {
fn next(&mut self) -> Option<&dyn miniserde::Serialize> {
let i = self.index;
self.index += 1;
self.values.get(i).map(|v| v as &dyn miniserde::Serialize)
}
}
#[repr(C)]
struct Place {
out: Option<TimeDelta>,
}
impl Place {
fn new(out: &mut Option<TimeDelta>) -> &mut Self {
unsafe { &mut *std::ptr::addr_of_mut!(*out).cast::<Place>() }
}
}
impl Visitor for Place {
fn seq(&mut self) -> miniserde::Result<Box<dyn Seq + '_>> {
Ok(Box::new(TimeDeltaSeqVisitor {
out: &mut self.out,
elements: [None, None],
index: 0,
}))
}
}
struct TimeDeltaSeqVisitor<'a> {
out: &'a mut Option<TimeDelta>,
elements: [Option<i64>; 2],
index: usize,
}
impl Seq for TimeDeltaSeqVisitor<'_> {
fn element(&mut self) -> miniserde::Result<&mut dyn Visitor> {
if self.index >= 2 {
return Err(miniserde::Error);
}
let slot = &mut self.elements[self.index];
self.index += 1;
Ok(Deserialize::begin(slot))
}
fn finish(&mut self) -> miniserde::Result<()> {
let secs = self.elements[0].ok_or(miniserde::Error)?;
let nanos = self.elements[1].ok_or(miniserde::Error)?;
if nanos < 0 || nanos >= 1_000_000_000 {
return Err(miniserde::Error);
}
*self.out = Some(
TimeDelta::new(secs, nanos as u32).ok_or(miniserde::Error)?,
);
Ok(())
}
}