use super::util::{capture_env_vars, get_terminal_size};
use serde::ser::SerializeStruct;
use serde::Serialize;
use std::collections::HashMap;
#[derive(Debug)]
pub(super) struct Header {
version: u8,
pub width: u16,
pub height: u16,
pub timestamp: Option<u64>,
pub idle_time_limit: Option<f64>,
pub title: Option<String>,
pub env: Option<HashMap<String, String>>,
}
fn serialize_or_skip<S, T>(
state: &mut S,
key: &'static str,
value: Option<&T>,
) -> Result<(), S::Error>
where
S: SerializeStruct,
T: Serialize,
{
if let Some(value) = value {
state.serialize_field(key, value)?;
} else {
state.skip_field(key)?;
}
Ok(())
}
impl Serialize for Header {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut len = 3;
if self.timestamp.is_some() {
len += 1;
}
if self.idle_time_limit.is_some() {
len += 1;
}
if self.title.is_some() {
len += 1;
}
if self.env.is_some() {
len += 1;
}
let mut state = serializer.serialize_struct("Header", len)?;
state.serialize_field("version", &self.version)?;
state.serialize_field("width", &self.width)?;
state.serialize_field("height", &self.height)?;
serialize_or_skip(&mut state, "timestamp", self.timestamp.as_ref())?;
serialize_or_skip(&mut state, "idle_time_limit", self.idle_time_limit.as_ref())?;
serialize_or_skip(&mut state, "title", self.title.as_ref())?;
serialize_or_skip(&mut state, "env", self.env.as_ref())?;
state.end()
}
}
impl Header {
pub fn new() -> Self {
let (width, height) = get_terminal_size();
Self {
version: 2,
width,
height,
timestamp: None,
idle_time_limit: None,
title: None,
env: Some(capture_env_vars(vec![
"SHELL".to_string(),
"TERM".to_string(),
])),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn header_serialize() -> serde_json::Result<()> {
let header = Header {
version: 2,
width: 80,
height: 24,
timestamp: None,
idle_time_limit: Some(2.0),
title: Some("My asciicast".to_string()),
env: None,
};
let expected =
r#"{"version":2,"width":80,"height":24,"idle_time_limit":2.0,"title":"My asciicast"}"#;
assert_eq!(serde_json::to_string(&header)?, expected);
Ok(())
}
}