use serde::Serialize;
use std::io::Write;
#[derive(Debug)]
pub(super) struct Event<'a> {
time: u128,
code: EventCode,
data: &'a str,
}
impl Serialize for Event<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeSeq;
let mut state = serializer.serialize_seq(Some(3))?;
#[allow(clippy::cast_precision_loss)]
let time = self.time as f64 / 1_000_000.0;
state.serialize_element(&time)?;
state.serialize_element(&self.code)?;
state.serialize_element(&self.data)?;
state.end()
}
}
impl<'a> Event<'a> {
pub const fn output(time: u128, data: &'a str) -> Self {
Self {
time,
code: EventCode::Output,
data,
}
}
pub const fn input(time: u128, data: &'a str) -> Self {
Self {
time,
code: EventCode::Input,
data,
}
}
pub const fn marker(time: u128, name: &'a str) -> Self {
Self {
time,
code: EventCode::Marker,
data: name,
}
}
pub const fn resize(time: u128, dim: &'a str) -> Self {
Self {
time,
code: EventCode::Resize,
data: dim,
}
}
pub fn write(&self, writer: impl Write) -> Result<(), serde_json::Error> {
let mut serializer = serde_json::Serializer::with_formatter(writer, Formatter);
self.serialize(&mut serializer)?;
Ok(())
}
}
#[derive(Debug)]
enum EventCode {
Output,
Input,
Marker,
Resize,
}
impl Serialize for EventCode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use EventCode::{Input, Marker, Output, Resize};
match self {
Output => serializer.serialize_str("o"),
Input => serializer.serialize_str("i"),
Marker => serializer.serialize_str("m"),
Resize => serializer.serialize_str("r"),
}
}
}
struct Formatter;
impl serde_json::ser::Formatter for Formatter {
fn write_f64<W>(&mut self, writer: &mut W, value: f64) -> std::io::Result<()>
where
W: ?Sized + std::io::Write,
{
write!(writer, "{value:.6}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn event_serialize() -> serde_json::Result<()> {
let pairs = [
(
Event::output(0, "Output event"),
r#"[0.000000,"o","Output event"]"#,
),
(
Event::input(1_000_000, "Input event"),
r#"[1.000000,"i","Input event"]"#,
),
(
Event::marker(1_000_001, "Marker event"),
r#"[1.000001,"m","Marker event"]"#,
),
(
Event::resize(1_002_000, "80x24"),
r#"[1.002000,"r","80x24"]"#,
),
];
for (event, expected) in &pairs {
let mut serialized = Vec::new();
event.write(&mut serialized)?;
let serialized = String::from_utf8(serialized).unwrap();
assert_eq!(serialized, *expected);
}
Ok(())
}
}