use-event-metadata 0.1.0

Ordered string metadata entries for RustUse event primitives.
Documentation
#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EventMetadataEntry {
    key: String,
    value: String,
}

impl EventMetadataEntry {
    pub fn new(key: impl Into<String>, value: impl Into<String>) -> Self {
        Self {
            key: key.into(),
            value: value.into(),
        }
    }

    pub fn key(&self) -> &str {
        &self.key
    }

    pub fn value(&self) -> &str {
        &self.value
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct EventMetadata {
    entries: Vec<EventMetadataEntry>,
}

impl EventMetadata {
    pub const fn new() -> Self {
        Self {
            entries: Vec::new(),
        }
    }

    pub fn with_entry(key: impl Into<String>, value: impl Into<String>) -> Self {
        let mut metadata = Self::new();
        metadata.insert(key, value);
        metadata
    }

    pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) {
        let key = key.into();
        if let Some(entry) = self.entries.iter_mut().find(|entry| entry.key == key) {
            entry.value = value.into();
        } else {
            self.entries.push(EventMetadataEntry::new(key, value));
        }
    }

    pub fn get(&self, key: &str) -> Option<&str> {
        self.entries
            .iter()
            .find(|entry| entry.key == key)
            .map(EventMetadataEntry::value)
    }

    pub fn entries(&self) -> &[EventMetadataEntry] {
        &self.entries
    }

    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    pub fn len(&self) -> usize {
        self.entries.len()
    }
}

#[cfg(test)]
mod tests {
    use super::{EventMetadata, EventMetadataEntry};

    #[test]
    fn stores_entry_accessors() {
        let entry = EventMetadataEntry::new("trace_id", "abc");

        assert_eq!(entry.key(), "trace_id");
        assert_eq!(entry.value(), "abc");
    }

    #[test]
    fn inserts_and_updates_entries() {
        let mut metadata = EventMetadata::with_entry("trace_id", "abc");

        metadata.insert("trace_id", "def");
        metadata.insert("source", "cli");

        assert_eq!(metadata.get("trace_id"), Some("def"));
        assert_eq!(metadata.get("source"), Some("cli"));
        assert_eq!(metadata.len(), 2);
    }

    #[test]
    fn exposes_entries_in_order() {
        let mut metadata = EventMetadata::new();
        metadata.insert("a", "1");
        metadata.insert("b", "2");

        assert_eq!(metadata.entries()[0].key(), "a");
        assert_eq!(metadata.entries()[1].key(), "b");
    }
}