use std::collections::HashMap;
use agp_datapath::{messages::AgentType, pubsub::proto::pubsub::v1::Message};
pub struct ProducerBuffer {
capacity: usize,
next: usize,
buffer: Vec<Option<Message>>,
map: HashMap<usize, usize>,
destination_name: AgentType,
destination_id: Option<u64>,
}
impl ProducerBuffer {
pub fn with_capacity(capacity: usize) -> Self {
ProducerBuffer {
capacity,
next: 0,
buffer: vec![None; capacity],
map: HashMap::new(),
destination_name: AgentType::default(),
destination_id: None,
}
}
pub fn get_capacity(&self) -> usize {
self.capacity
}
pub fn get_destination_name(&self) -> &AgentType {
&self.destination_name
}
pub fn get_destination_id(&self) -> Option<u64> {
self.destination_id
}
pub fn push(&mut self, msg: Message) -> bool {
if self.map.is_empty() {
(self.destination_name, self.destination_id) = msg.get_name();
}
let id = msg.get_id() as usize;
if self.map.contains_key(&id) {
return true;
}
if let Some(message) = &self.buffer[self.next] {
let to_remove = message.get_id() as usize;
self.map.remove(&to_remove);
}
self.buffer[self.next] = Some(msg);
self.map.insert(id, self.next);
self.next = (self.next + 1) % self.capacity;
true
}
pub fn clear(&mut self) {
self.buffer = vec![None; self.capacity];
self.next = 0;
self.map.clear();
}
pub fn get(&self, id: usize) -> Option<Message> {
match self.map.get(&id) {
None => None,
Some(index) => self.buffer[*index].clone(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use agp_datapath::messages::encoder::{Agent, AgentType};
use agp_datapath::pubsub::proto::pubsub::v1::SessionHeaderType;
use agp_datapath::pubsub::{AgpHeader, SessionHeader};
#[test]
fn test_producer_buffer() {
let mut buffer = ProducerBuffer::with_capacity(3);
assert_eq!(buffer.get_capacity(), 3);
let src = Agent::from_strings("org", "ns", "type", 0);
let name_type = AgentType::from_strings("org", "ns", "type");
let agp_header = AgpHeader::new(&src, &name_type, Some(1), None);
let h0 = SessionHeader::new(SessionHeaderType::Fnf.into(), 0, 0);
let h1 = SessionHeader::new(SessionHeaderType::Fnf.into(), 0, 1);
let h2 = SessionHeader::new(SessionHeaderType::Fnf.into(), 0, 2);
let h3 = SessionHeader::new(SessionHeaderType::Fnf.into(), 0, 3);
let h4 = SessionHeader::new(SessionHeaderType::Fnf.into(), 0, 4);
let p0 = Message::new_publish_with_headers(Some(agp_header), Some(h0), "", vec![]);
let p1 = Message::new_publish_with_headers(Some(agp_header), Some(h1), "", vec![]);
let p2 = Message::new_publish_with_headers(Some(agp_header), Some(h2), "", vec![]);
let p3 = Message::new_publish_with_headers(Some(agp_header), Some(h3), "", vec![]);
let p4 = Message::new_publish_with_headers(Some(agp_header), Some(h4), "", vec![]);
assert!(buffer.push(p0.clone()));
assert_eq!(buffer.get(0).unwrap(), p0);
assert_eq!(buffer.get(0).unwrap(), p0);
assert_eq!(buffer.get(0).unwrap(), p0);
assert_eq!(buffer.get(1), None);
assert!(buffer.push(p0.clone()));
assert!(buffer.push(p1.clone()));
assert!(buffer.push(p2.clone()));
assert_eq!(buffer.get(0).unwrap(), p0);
assert_eq!(buffer.get(1).unwrap(), p1);
assert_eq!(buffer.get(2).unwrap(), p2);
assert_eq!(buffer.get(3), None);
assert!(buffer.push(p3.clone()));
assert_eq!(buffer.get(0), None);
assert_eq!(buffer.get(1).unwrap(), p1);
assert_eq!(buffer.get(2).unwrap(), p2);
assert_eq!(buffer.get(3).unwrap(), p3);
assert_eq!(buffer.get(4), None);
assert!(buffer.push(p4.clone()));
assert_eq!(buffer.get(0), None);
assert_eq!(buffer.get(1), None);
assert_eq!(buffer.get(2).unwrap(), p2);
assert_eq!(buffer.get(3).unwrap(), p3);
assert_eq!(buffer.get(4).unwrap(), p4);
buffer.clear();
assert_eq!(buffer.get(0), None);
assert_eq!(buffer.get(1), None);
assert_eq!(buffer.get(2), None);
assert_eq!(buffer.get(3), None);
assert_eq!(buffer.get(4), None);
assert!(buffer.push(p0.clone()));
assert!(buffer.push(p1.clone()));
assert!(buffer.push(p2.clone()));
assert!(buffer.push(p3.clone()));
assert!(buffer.push(p4.clone()));
assert_eq!(buffer.get(0), None);
assert_eq!(buffer.get(1), None);
assert_eq!(buffer.get(2).unwrap(), p2);
assert_eq!(buffer.get(3).unwrap(), p3);
assert_eq!(buffer.get(4).unwrap(), p4);
}
}