sink.rs (1734B)
1 use alloc::string::ToString; 2 use alloc::vec::Vec; 3 use radroots_nostr::prelude::RadrootsNostrEvent; 4 use std::sync::Mutex; 5 6 pub trait RadrootsNostrEventSink: Send + Sync { 7 fn ingest_event(&self, event: &RadrootsNostrEvent) -> Result<(), String>; 8 } 9 10 #[derive(Default)] 11 pub struct RadrootsNostrInMemoryEventSink { 12 events: Mutex<Vec<RadrootsNostrEvent>>, 13 } 14 15 impl RadrootsNostrInMemoryEventSink { 16 pub fn new() -> Self { 17 Self::default() 18 } 19 20 pub fn events(&self) -> Vec<RadrootsNostrEvent> { 21 self.events 22 .lock() 23 .map(|guard| guard.clone()) 24 .unwrap_or_default() 25 } 26 27 pub fn len(&self) -> usize { 28 self.events.lock().map(|guard| guard.len()).unwrap_or(0) 29 } 30 31 pub fn is_empty(&self) -> bool { 32 self.len() == 0 33 } 34 } 35 36 impl RadrootsNostrEventSink for RadrootsNostrInMemoryEventSink { 37 fn ingest_event(&self, event: &RadrootsNostrEvent) -> Result<(), String> { 38 self.events 39 .lock() 40 .map_err(|_| "in-memory sink lock poisoned".to_string()) 41 .map(|mut guard| { 42 guard.push(event.clone()); 43 }) 44 } 45 } 46 47 #[cfg(test)] 48 mod tests { 49 use super::*; 50 use radroots_nostr::prelude::{RadrootsNostrEventBuilder, RadrootsNostrKeys}; 51 52 #[test] 53 fn in_memory_sink_tracks_events() { 54 let sink = RadrootsNostrInMemoryEventSink::new(); 55 let keys = RadrootsNostrKeys::generate(); 56 let event = RadrootsNostrEventBuilder::text_note("hello") 57 .sign_with_keys(&keys) 58 .expect("event should sign"); 59 60 sink.ingest_event(&event).expect("event should be accepted"); 61 assert_eq!(sink.len(), 1); 62 assert!(!sink.is_empty()); 63 } 64 }