tiny-counter 0.1.0

Track event counts across time windows with fixed memory and fast queries
Documentation
use crate::{formatter::Formatter, Result, SingleEventCounter};

/// JSON serialization format.
///
/// Human-readable format, useful for debugging and inspection.
#[derive(Debug, Clone, Copy)]
pub struct JsonFormat;

impl Formatter for JsonFormat {
    fn serialize(&self, value: &SingleEventCounter) -> Result<Vec<u8>> {
        serde_json::to_vec(value).map_err(|e| crate::Error::Serialization(e.to_string()))
    }

    fn deserialize(&self, bytes: &[u8]) -> Result<SingleEventCounter> {
        serde_json::from_slice(bytes).map_err(|e| crate::Error::Serialization(e.to_string()))
    }

    fn extension(&self) -> &'static str {
        ".json"
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{EventCounterConfig, SingleEventCounter};
    use chrono::Utc;

    #[test]
    fn test_json_roundtrip() {
        let formatter = JsonFormat;
        let now = Utc::now();
        let config = EventCounterConfig::default();
        let counter = config.create_counter(now);

        let bytes = formatter.serialize(&counter).unwrap();
        let decoded: SingleEventCounter = formatter.deserialize(&bytes).unwrap();

        // Verify structure matches
        assert_eq!(decoded.intervals().len(), counter.intervals().len());
    }

    #[test]
    fn test_json_is_readable() {
        let formatter = JsonFormat;
        let now = Utc::now();
        let config = EventCounterConfig::default();
        let counter = config.create_counter(now);

        let bytes = formatter.serialize(&counter).unwrap();
        let json_str = std::str::from_utf8(&bytes).unwrap();

        // Verify it's valid JSON
        assert!(json_str.contains("{"));
        assert!(json_str.contains("}"));
    }

    #[test]
    fn test_json_extension() {
        let formatter = JsonFormat;
        assert_eq!(formatter.extension(), ".json");
    }
}